【问题标题】:Understanding .then() ES6理解 .then() ES6
【发布时间】:2016-07-19 03:15:47
【问题描述】:

我在代码中遇到了一个让我困惑了很长时间的错误,我正在寻找一些解释。

在这段代码中,被注释掉的内部承诺导致了一个问题。一旦 setTimeout 命中,最后的 Promise.all() 就会继续,而不是在超时内解决之后。

用 promise 包装异步代码可以解决流程问题,但这是为什么呢?

本质上,为什么我们不能在 .then() 链中运行正常的异步代码,在异步回调结束时返回 Promise.resolve()?

var asyncPromise = function() {
    return new Promise(function(resolve, reject) {
        setTimeout(function() {
            console.log('Async Promise done');
            resolve();
        }, 1000);
    });
};

var generateSignupPromises = function(qty) {
    var promiseArray = [];
    for (var i = 1; i <= qty; i++) {
        promiseArray.push(
            function() {
                return asyncPromise()
                .then(function() {
                    console.log('Before Timeout');

                  //Uncommenting this fixes the issue
                  //return new Promise(function(resolve, reject) {
                        setTimeout(function() {
                            console.log('After Timeout');
                            //resolve();
                            return Promise.resolve();
                        }, 500);
                  //})
                });
            }
        );
    }
    return promiseArray;
};

var test = generateSignupPromises(1);

Promise.all([test[0]()])
.then(function() {
    console.log('Done');
});

运行代码链接:http://www.es6fiddle.net/imfdtuxc/

【问题讨论】:

  • 我真的不知道你想做什么,但return 内的setTimeout() 处理程序几乎没有多大意义;什么都不会关注返回值。
  • 厄运金字塔 + 大量匿名函数 = 不可读代码 + 意外行为。
  • setTimeout 不是异步的。它同步返回,导致您的 then() 返回未定义的“承诺”结尾。通过添加额外的行,它会返回另一个承诺,该承诺将等到resolve。顺便提一句。这不是应使用 Promise 的方式。

标签: javascript asynchronous promise es6-promise


【解决方案1】:

为什么我们不能在 .then() 链中运行正常的异步代码,在异步回调结束时返回 Promise.resolve()?

你完全可以。但是任何值——无论是一个承诺还是其他——从一个普通的异步回调中被returned 只是像往常一样被忽略。

在then 回调中启动异步操作没有任何改变,setTimeout 只是不返回承诺 - 而then 不会知道它可以等待的任何异步发生.

如果你想从回调中返回一个 Promise 并为该最终结果获得另一个 Promise,它必须是一个 then 回调:

asyncPromise()
.then(function() {
    return new Promise(function(resolve, reject) {
//  ^^^^^^
        setTimeout(resolve, 500);
    }).then(function() {
//     ^^^^^^^^^^^^^^^
        return Promise.resolve();
    });
});

【讨论】:

    【解决方案2】:

    Then 是一个同步函数,所以如果你想在 then 里面做异步任务,你必须返回一个 Promise。

    另外,Promise.all 期待一系列的承诺。不是数组的数组。

    var asyncPromise = function() {
      return new Promise(function(resolve, reject) {
        setTimeout(function() {
          console.log('Async Promise done');
          resolve();
        }, 1000);
      });
    };
    
    var generateSignupPromises = function(qty) {
      var promiseArray = [];
      for (var i = 1; i <= qty; i++) {
        promiseArray.push(
          function() {
            return asyncPromise()
            .then(function() {
              console.log('Before Timeout');
    
              //Uncommenting this fixes the issue
              return new Promise(function(resolve, reject) {
              setTimeout(function() {
                console.log('After Timeout');
                resolve();
                //return Promise.resolve();
              }, 500);
              })
            });
          }
        );
      }
      return promiseArray;
    };
    
    var test = generateSignupPromises(1);
    
    Promise.all([test[0]()])
    .then(function() {
      console.log('Done');
    });
    

    http://www.es6fiddle.net/imfe2sze/

    【讨论】:

      猜你喜欢
      • 2016-02-24
      • 1970-01-01
      • 2017-11-12
      • 1970-01-01
      • 2017-09-18
      • 2021-07-16
      • 2019-04-07
      • 1970-01-01
      • 2022-10-25
      相关资源
      最近更新 更多