【问题标题】:How to '$.all' a dynamic set of promises?如何“$.all”一组动态的承诺?
【发布时间】:2016-05-16 19:48:42
【问题描述】:

假设我们有 3 个 promise,我们将它们传递给 $q.all。这将返回一个新的 Promise,当 3 个 Promise 被解决时,该 Promise 也被解决。

现在,如果在解决 3 个 promise 之前,我实际上决定要解决第 4 个 promise,可以这样做吗?

我尝试了类似的方法:

var promises = [promise1, promise2, promise3];
var allDone = $q.all(promises);
promises.push(promise4);

在上面,allDone 在前 3 个 promise 解决后立即解决,但我希望它也等待第 4 个 promise。

或者我在这里错过了承诺的意义?也许我不应该在这种情况下使用承诺?

更新:正如回答的那样,$q.all 不能做我想做的事。我的问题:是否有另一种方法可以知道何时解决一组动态的承诺,即使这组发生变化?

【问题讨论】:

    标签: javascript angularjs promise


    【解决方案1】:

    您不能在事后向数组添加承诺并期望它会影响之前的.all().all() 不是这样工作的。你可以这样做:

    var promises = [promise1, promise2, promise3];
    var allDone = $q.all(promises);
    
    $q.all([allDone, promise4]).then(function() {
        // all four promises are done here
    }); 
    

    或者,您可以放弃 allDone 承诺并重新创建一个新的 .all(),如下所示:

    var promises = [promise1, promise2, promise3];
    var allDone = $q.all(promises);
    
    promises.push(promise4);
    var all4Done = $q.all(promises);
    

    根据您的 cmets,这是另一种可能性。假设您要调用的最终完成处理程序位于名为allDoneNow() 的函数中。然后,您可以执行以下操作:

    var promises = [promise1, promise2, promise3];
    var allDone = $q.all(promises);
    allDone.then(function(results) {
        // if no new promises have been added to the array
        if (promises.length === results.length) {
            // call our final handler
            return allDoneNow(results);
        } else {
            // wait for any new promises
            return $q.all(promises).then(allDoneNow);
        }
    });
    
    promises.push(promise4);
    

    或者,如果您希望它递归以便它不断检查更多,您可以将它放在一个可以递归使用的函数中:

    function waitAll(promiseArray) {
        return $q.all(promiseArray).then(function(results) {
            if (promiseArray.length <= results.length) {
                // everything currently in the promiseArray is now done
                return results;
            } else {
                // there are some new things in the promiseArray so
                // wait until they are done
                return waitAll(promiseArray);
            }
        });
    }
    
    
    var promises = [promise1, promise2, promise3];
    waitAll(promises).then(function(results) {
        // all promises currently in the promises array are done
    });
    
    promises.push(promise4);
    

    【讨论】:

    • 嗯,但这需要我以某种方式取消附加到第一个 $q.all 的任何 .then() 回调。我希望有一个更简单的解决方案:-)。
    • @user125661 - 您已经注册了一个处理程序来完成三个承诺。你无法改变这一点。您可以添加新的处理程序,以通知您新创建的条件。如果,当您拥有前三个 Promise 时,您知道在前三个 Promise 完成之前您可能还有更多 Promise,那么请不要注册最终处理程序。注册一个虚拟处理程序,其工作是检查是否还有其他需要等待的承诺,如果没有,则它可以调用处理程序。
    • 有道理!我想的另一个解决方案可能是在四个承诺的集合中添加一个虚拟承诺。一旦我知道应该更改原始承诺集,我就可以拒绝那个虚拟承诺,并按照您上面的建议设置一个新的 $q.all。
    • @user125661 - 我在答案中添加了一个示例。
    • @user125661 - 我在答案中添加了递归实现。
    【解决方案2】:

    如果您可以查看$q all() 函数的源代码,您会发现它只是使用 forEach() 遍历所有 Promise 并返回另一个 Promise,稍后将解决所有结果。

    因此,如果您将另一个 Promise 推送到数组中,它根本不会影响它,因为它已经设置了所有 Promise 并使用您的 Promise 数组完成。

    【讨论】:

    • 谢谢!我想我的实际问题是:有没有办法让我得到这样的行为?
    猜你喜欢
    • 1970-01-01
    • 2018-03-18
    • 2016-05-16
    • 2018-08-06
    • 1970-01-01
    • 2017-07-02
    • 2017-11-07
    • 2014-08-30
    • 2018-05-11
    相关资源
    最近更新 更多