Почему этот простой асинхронный код обещает уменьшить код? - PullRequest
1 голос
/ 27 июня 2019

Почему этот код работает идеально? Я не знаю, почему этот код работает.

Метод цикла ничего не возвращает, поэтому аккумулятор должен быть нулевым, и этот код не должен работать.

const arr = [1, 2, 3, 4];

  const awaitFunc = (val) => new Promise(function (resolve, reject) {
    setTimeout(function () {
      console.log('awaitFunc', val);
	  resolve();
	}, 500);
  });
  
  const start = async () => {
    console.log('start');

    await arr.reduce(async (promise, val, index) => {
      await promise;

      console.log('reduce loop', val);
      
      await awaitFunc(val);
    }, Promise.resolve());

    console.log('end');
  };

  start();

результат выглядит следующим образом.

start
reduce loop 1
(500ms)
awaitFunc 1
reduce loop 2
(500ms)
awaitFunc 2
reduce loop 3
(500ms)
awaitFunc 3
reduce loop 4
(500ms)
awaitFunc 4
end

1 Ответ

1 голос
/ 27 июня 2019

Функция async автоматически возвращает Обещание.Если функция содержит await с, Обещание будет выполнено после того, как все await с завершатся (и интерпретатор достигнет нижней части функционального блока).Поскольку аккумулятор является функцией async, он автоматически возвращает Обещание, поэтому имеет смысл await разрешение Обещания, возвращенного итерацией last (последний запуск аккумулятора).

Итак,

 await arr.reduce(async (promise, val, index) => {
   await promise;

   console.log('reduce loop', val);

   await awaitFunc(val);
 }, Promise.resolve());

эквивалентно

await arr.reduce((promise, val, index) => {
  return promise.then(() => {
    console.log('reduce loop', val);
    return awaitFunc(val);
    // ^^^^^^^ returned end of Promise chain, so accumulator promise in next reduce loop will resolve
    // once above promise resolves
  });
}, Promise.resolve());

или

 await arr.reduce((promise, val, index) => {
   // just for illustration, don't use the explicit Promise construction antipattern
   return new Promise((resolve) => {
     // await promise;
     promise.then(() => {
       console.log('reduce loop', val);
       // await awaitFunc(val);
       awaitFunc(val).then(resolve)
       //                  ^^^^^^^ Accumulator promise in next reduce loop will resolve
     });
   });
 }, Promise.resolve());

const arr = [1, 2, 3, 4];

const awaitFunc = (val) => new Promise(function (resolve, reject) {
  setTimeout(function () {
    console.log('awaitFunc', val);
    resolve();
  }, 500);
});

const start = async () => {
  console.log('start');

   await arr.reduce((promise, val, index) => {
     // just for illustration, don't use the explicit Promise construction antipattern
     return new Promise((resolve) => {
       // await promise;
       promise.then(() => {
         console.log('reduce loop', val);
         // await awaitFunc(val);
         awaitFunc(val).then(resolve)
       });
     });
   }, Promise.resolve());

  console.log('end');
};

start();
...