我的问题是我不知道如何知道动态 promise 数组何时解决了所有 promise 。
这里是一个例子:
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*/});
我这里有个问题。当前 2 个 promise 得到解决时,Promise.all
行为将被执行,但是,在这 2 个 promise 得到解决之前,添加了第三个 promise ,并且不会考虑这个新的 promise 。
所以,我需要的是这样的话:“嘿 Promise.all
,你有一个动态数组要检查”。我该怎么做?
请记住,这只是一个示例。我知道我可以将 Promise.all 行移动到最后一行,但实际上,当另一个 Promise 解决时,新的 Promise 是动态添加的,并且新的 Promise 也可以添加新的 Promise,所以,它是一个真正的动态数组。
我的真实用例是这样的:
- 我使用 Twitter API 检查是否有新推文(使用搜索 Api)。
- 如果我发现新的推文,我会将其添加到 MongoDB(这里有 Promises)。
- 如果这些新推文与我的 MongoDB 中没有的用户相关(这里我们有新的 promise ,因为我必须去 MongoDB 来检查我是否有该用户),我们可以使用 Twitter API 来获取用户信息(更多 promise ),然后我们将这些新用户添加到 MongoDB(是的,更多 promise )。
- 然后,我转到 MongoDB 插入新值,将新推文与这些新用户关联起来(更多 promise !wiii!)。
- 当对 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 函数。你是怎么做到的?:
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/
最佳答案
您可以创建一个简洁的小递归函数来包装 Promise.all
来处理对原始 Promise 的添加:
/**
* Returns a Promise that resolves to an array of inputs, like Promise.all.
*
* If additional unresolved promises are added to the passed-in iterable or
* array, the returned Promise will additionally wait for those, as long as
* they are added before the final promise in the iterable can resolve.
*/
function iterablePromise(iterable) {
return Promise.all(iterable).then(function(resolvedIterable) {
if (iterable.length != resolvedIterable.length) {
// The list of promises or values changed. Return a new Promise.
// The original promise won't resolve until the new one does.
return iterablePromise(iterable);
}
// The list of promises or values stayed the same.
// Return results immediately.
return resolvedIterable;
});
}
/* Test harness below */
function timeoutPromise(string, timeoutMs) {
console.log("Promise created: " + string + " - " + timeoutMs + "ms");
return new Promise(function(resolve, reject) {
window.setTimeout(function() {
console.log("Promise resolved: " + string + " - " + timeoutMs + "ms");
resolve();
}, timeoutMs);
});
}
var list = [timeoutPromise('original', 1000)];
timeoutPromise('list adder', 200).then(function() {
list.push(timeoutPromise('newly created promise', 2000));
});
iterablePromise(list).then(function() { console.log("All done!"); });
在带有 lambda 且没有注释的 ES6 中,这甚至可以更短:
function iterablePromise(iterable) {
return Promise.all(iterable).then((resolvedIterable) => {
if (iterable.length != resolvedIterable.length) {
return iterablePromise(iterable);
}
return resolvedIterable;
});
}
或者,如 Rads their answer 中用 async
/await
表示,但作为一个函数:
async function iterablePromise(iterable) {
let resolvedIterable = [];
while (iterable.length !== resolvedIterable.length) {
resolvedIterable = await Promise.all(iterable); // implicit "then"
}
return resolvedIterable;
}
请记住,这仅涵盖加法,并且仍然有点危险:您需要确保回调顺序,以便任何正在运行的 promise 将自己添加到列表之前 Promises.all
可以调用回调。
关于javascript - 如何知道动态 "iterable"参数中的所有 Promise 何时已解决?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38838332/