如何知道何时解决所有Promises在动态的“可迭代”参数? [英] How to know when all Promises are Resolved in a dynamic "iterable" parameter?

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

问题描述



这里有一个例子:

  var promiseArray = []; 
promiseArray.push(new Promise(){/ * blablabla * /});
promiseArray.push(new Promise(){/ * blablabla * /});
Promise.all(promiseArray).then(function(){
//当这两个承诺解决时,这将被执行
});
promiseArray.push(new Promise(){/ * blablabla * /});

这里有一个问题。当前2个承诺得到解决时,将执行 Promise.all 行为,但在这两个承诺得到解决之前,第三个承诺将被添加,而新的一个将不会请记住。



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



请记住,这只是一个例子。我知道我可以将 Promise.all 的行移到最后一行,但实际上当另一个承诺得到解决时,新的承诺将被动态添加,新的承诺可以添加新的承诺所以,这是一个非常动态的数组。



我的真实用例是这样的:


  1. 我使用Twitter API来检查是否有新的Tweets(使用搜索Api)。

  2. 如果我发现新的Tweets,我将其添加到一个MongoDB(这里我们有承诺)。

  3. 如果这些新的Tweets与我在MongoDB中没有的用户相关(这里我们有新的承诺,因为我必须去到MongoDB检查我是否拥有该用户),我们转到Twitter API获取用户信息(更多承诺),并将这些新用户添加到MongoDB(是的,更多的承诺)。

  4. 然后,我去MongoDB插入新的值来将新的推文与这些新用户相关联(更多的承诺!wiii!)。

  5. 当MongoDB的所有查询都被解析(所有选择,更新,插入),关闭MongoDB连接。

另一个难题:

  var allPromises = []; 

allPromises.push(new Promise(function(done,fail){
mongoDB.connect(function(error){
//因为mongoDB与回调而不是promises一起使用
if(error)
fail();
else
ajax.get('/ whatever')然后(function(){
if(somethingHappens){
allPromises.push(new Promise(function(done,fail){//这个承诺永远不会在帐户
// bla bla bla
if(somethingHappens){
allPromises .push(新的Promise(功能(完成,失败){//这个承诺永远不会在帐户
// bla bla bla
}));
} else {
ajax.get('/ whatever / 2')然后(function(){
if(somethingHappens){
allPromises.push(new Promise(function(done,fail){//这个承诺永远不会在帐户
// bla bla bla
}));
}
});
}
}));
} else {
ajax.get('/ whatever / 2')然后(function(){
if(somethingHappens){
allPromises.push(new Promise (完成,失败){//这个承诺永远不会在帐户
// bla bla bla
if(somethingHappens){
allPromises.push(new Promise(function(done, ){//这个承诺永远不会被考虑在
// bla bla bla
}));
} else {
ajax.get('/ whatever / 2' ).then(function(){
if(somethingHappens){
allPromises.push(new Promise(function(done,fail){//这个承诺永远不会考虑到
// bla bla bla
}));
}
});
}
}));
}
});
}
});
});
}));

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

所以,现在,一个美丽的例子。当最后一个(我们不知道最后一个)承诺被调用时,我们需要调用 showAllTheInformation 函数。你如何做?:

  var name ='anonimus'; 
var date ='我们不知道';

函数userClikOnLogIn(){
$ http.get('/ login / user / password')然后(function(data){
if(data.logguedOk){
$ http.get('/ checkIfIsAdmin')然后(function(data){
if(data.yesHeIsAnAdmin){
$ http.get('/ getTheNameOfTheUser' 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/

解决方案

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



如果异步填充数组,则应该获得该数组的承诺,并使用 .then(Promise.all.bind(Promise))。如果你不知道什么时候停止添加承诺,这是不可能的,因为它们可能根本不会被解决。






关于你的美丽例子,你将要了解链接魔法。正如我先前在评论中所说的那样,你必须从每个你正在做任何异步操作的函数中获得 return 的承诺。确实,只需添加缺少的返回 s:

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

userClikOnLogIn()然后(function showAllTheInformation(){
// ^^^^^现在可以链接到它!
alert('Hi '+ name +'今天是:'+ date);
});

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


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

Here an example:

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*/});

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.

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

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. I use Twitter API to check if there are new Tweets (using the Search Api).
  2. In case I found new Tweets, I add it to a MongoDB (here we have Promises).
  3. In case that those new Tweets are related to a user that I do not have in my MongoDB (here we have new promises because I have to go to MongoDB to check if I have that user), we go to Twitter API to get user info (more promise) and we add those new users to MongoDB (yes, more promises).
  4. Then, I go to MongoDB to insert new values to associate the new tweets with those new users (more promises! wiii!).
  5. When all the queries to MongoDB are Resolved (all the selects, updates, inserts), close the MongoDB connection.

Another hard example:

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()!
});

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);
}

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

解决方案

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.

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.


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.

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

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