Как обещание решается в данном коде JavaScript с использованием Array.reduce()?

#javascript #es6-promise

#javascript #es6-обещание

Вопрос:

Пожалуйста, обратитесь к следующему JavaScript коду:

 var arr = [30, 40, 10, 50, 20];
var fun = function(n) {
  console.log("Before Promise => n: "   n);
  return new Promise(resolve => {
    console.log("After Promise => n: "   n);
    setTimeout(() => {
      console.log("Promise Resolved => n: "   n);
      resolve(0);
    }, n * 30);
  });
}
arr.reduce((p, v) => p.then(fun(v)), Promise.resolve(0));  

1. Пожалуйста, поправьте меня, если я ошибаюсь, это Array.reduce() уменьшит вышеуказанное в следующей Promise цепочке:

 Promise.resolve(0).then(fun(30)).then(fun(40)).then(fun(10)).then(fun(50)).then(fun(20)).
  

2. Почему вывод не такой, как показано ниже:

 Promise Resolved => n: 30
Promise Resolved => n: 40
Promise Resolved => n: 10
Promise Resolved => n: 50
Promise Resolved => n: 20
  

3. И почему результат такой, как указано выше, если я изменяю, n*30 скажем, с фиксированным временем 500 ?

Ответ №1:

.then принимает функцию в качестве параметра, но вы делаете:

 p.then(fun(v))
  

Это вызывает fun немедленно, не дожидаясь p разрешения, и передает возвращенное обещание .then . Это похоже на выполнение

 Promise.then(Promise.resolve(6))
         //  ^^^ but .then only accepts a function as a parameter
  

в этом нет никакого смысла.

Измените на обратный вызов, который при вызове вызывает fun и возвращает fun обещание:

 var arr = [30, 40, 10, 50, 20];
var fun = function(n) {
    console.log("Before Promise => n: "   n);
    return new Promise(resolve => {
        console.log("After Promise => n: "   n);
        setTimeout(() => {
            console.log("Promise Resolved => n: "   n);
            resolve(0);
        }, n*30);
    });
}
arr.reduce((p, v) => p.then(() => fun(v)), Promise.resolve(0));
//                          ^^^^^^  

Ответ №2:

Array.reduce() уменьшит вышеуказанное как следующую цепочку обещаний

ДА.

Почему результат не соответствует ожиданиям?

Потому что «цепочка» обещаний нарушена. Для правильной цепочки вам необходимо передать функции обратного вызова в then :

 Promise.resolve(0).then(() => fun(30)).then(() => fun(40)).then(() => fun(10)).then(() => fun(50)).then(() => fun(20));
//                      ^^^^^               ^^^^^               ^^^^^               ^^^^^               ^^^^^
  

Сделайте то же самое в своем редукторе:

 arr.reduce((p, v) => p.then(() => fun(v)), Promise.resolve(0));