【问题标题】:JavaScript: Perform a chain of promises synchronouslyJavaScript:同步执行一系列承诺
【发布时间】:2016-02-01 13:55:54
【问题描述】:

我有一个请求承诺,我需要在一个循环中执行,例如:

var ids = [1,2,3];
doPromise(1).then(function(){
  doPromise(2).then(function(){
    doPromise(3);
  }
})

问题是我永远不知道数组中有多少元素,所以我需要一个动态模式。是否可以混合使用同步和异步世界,以便一次只有一个请求处于活动状态(顺序不重要)?

【问题讨论】:

    标签: javascript loops promise


    【解决方案1】:

    依次迭代数组的经典方法是,对每个数组元素调用一些异步操作,方法是使用.reduce() 并链接到如下所示的初始承诺:

    问题是我永远不知道数组中有多少元素,所以 我需要一个动态模式。

    您可以使用一系列承诺来对它们进行排序。为此,使用.reduce() 迭代数组很有用,因为它提供了正确的迭代类型,可以在迭代数组时跟踪累积值(在这种情况下是一个承诺)。您可以使用额外的变量使几乎任何数组迭代方案都工作,这与.reduce() 非常吻合:

    var ids = [1,2,3,4,5,6,7];
    ids.reduce(function(p, item) {
        return p.then(function() {
            return doPromise(item);
        });
    }, Promise.resolve()).then(function(results) {
        // all done here with array of results
    });
    

    这会将一个已解决的 Promise 传递给 ids.reduce() 作为 Promise 链的头部。然后,它对该承诺执行.then() 并为数组中的每个项目返回一个新承诺(通过.reduce() 回调)。 .reduce() 调用的最终结果将是一个承诺,当它被解决时意味着整个链已经完成。

    理解这一点的关键是要记住 p.then() 返回一个新的 Promise,因此我们只需在每个新 Promise 上继续调用 .then() 并从每个 .then() 处理程序中的每个操作返回 Promise。这具有将所有 Promise 链接到一个顺序链中的效果。

    是否可以混合同步和异步世界,这样只有一个 请求在某个时刻处于活动状态(顺序不重要)?

    我不确定您所说的“混合同步和异步世界”是什么意思。确保一次只有一个请求在进行中的方法是将它们排序为一个接一个,这样下一个请求只有在前一个请求完成时才开始。这也恰好保证了执行顺序,即使您说在这种情况下这并不重要,但它是确保一次只有一个在运行中的副产品。

    还有,这是一个有效的 sn-p:

    function log(msg) {
        var d = document.createElement("div");
        d.textContent = msg;
        document.body.appendChild(d);
    }
    
    function doPromise(x) {
        return new Promise(function(resolve) {
            setTimeout(function() {
                log(x);
                resolve(x);
            }, Math.floor(Math.random() * 1000));
        });
    }
    
    var ids = [1,2,3,4,5,6,7];
    ids.reduce(function(p, item) {
        return p.then(function() {
            return doPromise(item);
        });
    }, Promise.resolve()).then(function() {
        // all done here
        log("all done");
    });

    【讨论】:

    • 非常感谢您这篇详尽而有价值的帖子。虽然我的设置有点多(复杂,因为每次迭代都包含一系列 Promise),但这是一个很好的入门。非常感谢!
    • 非常感谢。这有助于我解决我的问题。顺便说一句,这里的最终结果只是最后一个结果,而不是所有结果的数组,但我们可以保留从先前的承诺解析的参数:p.then(function(result) {...}
    • 在我看来,results 只是最后一个承诺的结果,而不是所有结果的数组
    • @scibuff - 是的,它是一个.reduce(),所以它就是这样工作的。如果你想累积一个结果数组,你可以,但你必须自己做,reduce() 末尾的值可能是你的数组。这段代码展示了如何使用.reduce() 对异步操作进行排序。如今,使用for 循环和await 会更容易。
    猜你喜欢
    • 1970-01-01
    • 2020-08-10
    • 1970-01-01
    • 2018-04-28
    • 2013-12-04
    • 1970-01-01
    • 2018-07-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多