如何知道所有 Promise 何时在动态“可迭代"中被解析范围? [英] How to know when all Promises are Resolved in a dynamic "iterable" parameter?

查看:15
本文介绍了如何知道所有 Promise 何时在动态“可迭代"中被解析范围?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的问题是我不知道如何知道动态承诺数组何时解决了所有承诺.

My problem is that I don't know how to know when a dynamic promise array has all the promises resolved.

这里有一个例子:

var promiseArray = [];
promiseArray.push(new Promise(){/*blablabla*/});
promiseArray.push(new Promise(){/*blablabla*/});
Promise.all(promiseArray).then(function(){
    // This will be executen when those 2 promises are solved.
});
promiseArray.push(new Promise(){/*blablabla*/});

我这里有问题.Promise.all 行为将在前 2 个承诺解决后执行,但是,在这两个承诺解决之前,添加了第三个承诺,并且不会考虑新的承诺.

I have a problem here. The Promise.all behavior will be executed when the previous 2 promises are solved, BUT, before those 2 promises were solved, a third promise where added and this new one won't be take in account.

所以,我需要的是这样说:嘿Promise.all,你有一个动态数组要检查".我该怎么做?

So, what I need, is say something like: "Hey Promise.all, you have a dynamic array to check". How can I do it?

请记住,这只是一个示例.我知道我可以将 Promise.all 行移到最后一行,但实际上新的 Promise 是在解决另一个 Promise 时动态添加的,并且新的 Promise 也可以添加新的 Promise,所以,它是一个真正动态的数组.

Remember that this is just an example. I know I can move the line Promise.all to the last line, but actually the new promises are added dynamically when another promises are solved, and the new promises could add new promises as well, so, it's a really dynamic array.

我的实际用例是这样的:

The real use case that I have is something like this:

  1. 我使用 Twitter API 检查是否有新推文(使用 Search Api).
  2. 如果我发现了新推文,我会将其添加到 MongoDB(这里有 Promise).
  3. 如果这些新推文与我的 MongoDB 中没有的用户相关(这里我们有新的承诺,因为我必须去 MongoDB 来检查我是否有那个用户),我们去 Twitter API 以获取用户信息(更多承诺),然后我们将这些新用户添加到 MongoDB(是的,更多承诺).
  4. 然后,我去 MongoDB 插入新值以将新推文与这些新用户相关联(更多承诺!wiii!).
  5. 当对 MongoDB 的所有查询都得到解决(所有选择、更新、插入)后,关闭 MongoDB 连接.

另一个困难的例子:

var allPromises = [];

allPromises.push(new Promise(function(done, fail){
    mongoDB.connect(function(error){
        //Because mongoDB works with callbacks instead of promises
        if(error)
            fail();
        else
            ajax.get('/whatever').then(function(){
                if (somethingHappens) {
                    allPromises.push(new Promise(function(done, fail){ //This promise never will be take in account
                        // bla bla bla
                        if (somethingHappens) {
                            allPromises.push(new Promise(function(done, fail){ //This promise never will be take in account
                                // bla bla bla
                            }));
                        } else {
                            ajax.get('/whatever/2').then(function(){
                                if (somethingHappens) {
                                    allPromises.push(new Promise(function(done, fail){ //This promise never will be take in account
                                        // bla bla bla
                                    }));
                                }
                            });
                        }
                    }));
                } else {
                    ajax.get('/whatever/2').then(function(){
                        if (somethingHappens) {
                            allPromises.push(new Promise(function(done, fail){ //This promise never will be take in account
                                // bla bla bla
                                    if (somethingHappens) {
                                        allPromises.push(new Promise(function(done, fail){ //This promise never will be take in account
                                            // bla bla bla
                                        }));
                                    } else {
                                        ajax.get('/whatever/2').then(function(){
                                            if (somethingHappens) {
                                                allPromises.push(new Promise(function(done, fail){ //This promise never will be take in account
                                                    // bla bla bla
                                                }));
                                            }
                                        });
                                    }
                            }));
                        }
                    });
                }
            });
    });
}));

Promise.all(allPromises).then(function(){
    // Soooo, all work is done!
    mongodb.close()!
});

那么,现在,一个美丽的例子.当最后一个(我们不知道哪个是最后一个)promise 被调用时,我们需要调用 showAllTheInformation 函数.你是怎么做的?:

So, now, a beauty example. We need to call the showAllTheInformation function when the last (we don't know which is the last) promise is called. How do you do it?:

var name = 'anonimus';
var date = 'we do not know';

function userClikOnLogIn() {
    $http.get('/login/user/password').then(function(data){
        if (data.logguedOk) {
            $http.get('/checkIfIsAdmin').then(function(data){
                if (data.yesHeIsAnAdmin) {
                    $http.get('/getTheNameOfTheUser').then(function(data){
                        if(data.userHasName) {
                            $http.get('/getCurrentDate').then(function(data){
                                currentDate = data.theNewCurrentDate;
                            });
                        }
                    });
                }
            });
        }
    });
}

function showAllTheInformation() {
    alert('Hi ' + name + ' today is:' + date);
}

这是另一个具有更多上下文的示例:https://jsfiddle.net/f0a1s79o/2/

here another example with more context: https://jsfiddle.net/f0a1s79o/2/

推荐答案

没有出路.在调用 Promise.all 之前,您必须将所有承诺放入数组中.在您提供的示例中,这就像将最后一行移到顶部一样简单.

There's no way out. You have to put all the promises in the array before calling Promise.all in it. In the example you presented, that's as simple as moving the last line to the top.

如果你异步填充数组,你应该得到该数组的一个promise,并使用.then(Promise.all.bind(Promise)).如果您不知道何时停止添加承诺,无论如何这是不可能的,因为它们可能永远不会全部解决.

In case you are asynchronously filling the array, you should get a promise for that array, and use .then(Promise.all.bind(Promise)). If you don't know when you stop adding promises, this is impossible anyway as they might never all be resolved at all.

关于您的美容示例",您将需要了解链接的魔力.正如我之前在评论中所说的那样,您必须从每个异步执行任何操作的函数中return 一个承诺.实际上,只需添加缺少的 returns:

Regarding your "beauty example", you will want to learn about the magic of chaining. As I previosly said in the comments, you have to return a promise from every function in which you are doing anything asynchronous. Indeed, just add the missing returns:

function userClikOnLogIn() {
    return $http.get('/login/user/password').then(function(data){
//  ^^^^^^
        if (data.logguedOk) {
            return $http.get('/checkIfIsAdmin').then(function(data){
//          ^^^^^^
                if (data.yesHeIsAnAdmin) {
                    return $http.get('/getTheNameOfTheUser').then(function(data){
//                  ^^^^^^
                        if(data.userHasName) {
                            return $http.get('/getCurrentDate').then(function(data){
//                          ^^^^^^
                                currentDate = data.theNewCurrentDate;
                            });
                        }
                    });
                }
            });
        }
    });
}

userClikOnLogIn().then(function showAllTheInformation() {
//               ^^^^^ now you can chain onto it!
    alert('Hi ' + name + ' today is:' + date);
});

这里没有动态增长的承诺数组,只是每个函数都为它所做的事情的(异步)结果返回一个承诺.

There is no array of promises here that dynamically grows, it's just that every function is returning a promise for the (asynchronous) result of the things it does.

这篇关于如何知道所有 Promise 何时在动态“可迭代"中被解析范围?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆