Promise.all()没有按照预期的顺序解析承诺
Promise.all() is not resolving promises in the expected order
如果我正确理解promise .all(),我希望这段代码在向控制台输出之前只输出拒绝承诺的原因需要5秒。
function firstAsyncFunction() {
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve(console.log('First async function has been resolved!'));
}, 500);
});
}
function secondAsyncFunction() {
return new Promise(function(resolve, reject) {
setTimeout(function(){
resolve(console.log('Second async function has been resolved!'));
}, 2000);
});
}
function thirdAsyncFunction() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject('Internal server error'); // rejected for some reason
}, 5000);
});
};
Promise.all([secondAsyncFunction(), firstAsyncFunction(), thirdAsyncFunction()])
.then(function(values){
values.forEach(function(value){
console.log(value);
});
}).catch(function(err){
console.log(err);
});
相反,前两个承诺被解决,然后最后一个承诺被拒绝。此外,前两个承诺甚至没有按照它们传递给Promise.all()的顺序解析。我是否需要改变我的承诺来看到我期待的行为?
编辑
Promise.all()确实会等待传递给它的可迭代对象中的所有承诺都解决。我的第一个线索是控制台输出未定义的事实(感谢Jaromanda X)。如果我在解析firstAsyncFunction()和secondAsyncFunction()时删除对console.log()的调用,下面的代码段就像我期望的那样工作:
function firstAsyncFunction() {
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve('First async function has been resolved!');
}, 1000);
});
}
function secondAsyncFunction() {
return new Promise(function(resolve, reject) {
resolve('Second async function has been resolved!');
});
}
function thirdAsyncFunction() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
reject('Internal server error');
}, 5000);
});
};
Promise.all([
thirdAsyncFunction(),
firstAsyncFunction(),
secondAsyncFunction()
])
.then(function(values){
values.forEach(function(value){
console.log(value);
});
})
.catch(function(err){
console.log(err);
});
五秒钟后,我只看到"内部服务器错误"。promise .all()拒绝其他的承诺,即使它们比被拒绝的承诺解决得更快。是的,Promise.all()解析的值将与作为参数传入的可迭代对象中的承诺顺序相同。谢谢你的帮助!
再举一个例子:
function firstAsyncFunction() {
return new Promise(function(resolve, reject){
setTimeout(function(){
resolve('First async function has been resolved!');
}, 1000);
});
}
function secondAsyncFunction() {
return new Promise(function(resolve, reject) {
resolve('Second async function has been resolved!');
});
}
function thirdAsyncFunction() {
return new Promise(function(resolve, reject) {
setTimeout(function() {
resolve({
users: [
{ name: 'Ronnie', age: 22 },
{ name: 'Bobby', age: 21 },
{ name: 'Ricky', age: 21 },
{ name: 'Mike', age: 20 }
]
});
}, 5000);
});
};
Promise.all([thirdAsyncFunction(), firstAsyncFunction(), secondAsyncFunction()])
.then(function(values){
values.forEach(function(value){
console.log(value);
});
})
.catch(function(err){
console.log(err);
});
五秒后,这段代码将输出:
{ users:
[ { name: 'Ronnie', age: 22 },
{ name: 'Bobby', age: 21 },
{ name: 'Ricky', age: 21 },
{ name: 'Mike', age: 20 } ] }
First async function has been resolved!
Second async function has been resolved!
正是我们想要的
承诺。一切都没有强加任何秩序的承诺,他们履行时,他们履行
第三个承诺在其他两个承诺"解决"之后被"拒绝",所以前两个承诺在最后一个承诺被拒绝之前被解决的事实是可以预料的
顺便说一下,您的前两个Promise正在解析值undefined
并输出到控制台-这就是为什么您可能认为Promise。所有人都在做一些不应该做的事情
我是否需要以不同的方式撰写我的承诺来看到我期望的行为?
你不会得到你所期望的行为,因为你期望承诺以特定的顺序解决,唯一可能发生的方式是承诺等待前一个承诺在它可以履行之前被履行,所以时间将是累积的,而不是并行的,所以在这种情况下,你不会得到拒绝7.5秒而不是你"期望"的5秒
Promise的then
或catch
函数。只有当所有的承诺都被解决或其中一个承诺被拒绝时,才会调用All。单个承诺可以以任何顺序解析(这就是承诺的全部意义——它们是异步的,可以在它们喜欢的时候完成它们应该完成的事情)
也就是说,如果你标记你的承诺会更清楚。所有的console.log都不一样,像这样
Promise.all([secondAsyncFunction(), firstAsyncFunction(), thirdAsyncFunction()])
.then(function (values) {
values.forEach(function (value) {
console.log('then:' + value);
});
}).catch(function (err) {
console.log(err);
});
你可能把控制台弄混了。
then
回调中的承诺。 Promise.all
并行运行您传递给它的所有promise。当承诺不相互依赖,而您需要同时执行这两个承诺时,这很有用。例如,在集成测试中,您需要向服务器注册两个客户机。你需要等待两个任务完成,但是同时启动两个任务可以将等待时间减少一半。
如果你想按顺序运行它们,你可以链接你的承诺,从一个到下一个返回结果:
firstAsyncFunction
.then(secondAsyncFunction)
.then(thirdAsyncFunction)
.then(function(values) {
console.log(values)
}, function(err) {
console.log(err);
});
如果您希望从所有三个调用返回聚合数据,您还需要修改您的承诺,以在数组(或对象)中返回它们的值。例如:
- firstAsyncFunction获取
userId
并返回{ name: 'Bob' }
- secondAsyncFunction获取
userObject
并返回{ name: 'Bob', car: 'Porsche' }
- thirdAsyncFunction获取
userObject
并返回{ name: 'Bob', car: 'Porsche', kids: 5 }
只是补充一下别人说过的话。
的承诺。all不按顺序运行。
下面是一个在ES6中顺序运行异步函数的例子
/**
* Runs async functions sequentially
* @param Function[]
* @return Promise<any>
*/
function runSequentially(functions) {
return functions.reduce((promise, next) => {
return promise.then(next);
}, Promise.resolve());
}
/**
* Full Example
*/
function foo()
{
return new Promise(( resolve, reject )=>{
resolve();
})
}
function boo() {
return new Promise((resolve, reject) => {
resolve();
})
}
function baz() {
return new Promise((resolve, reject) => {
resolve();
})
}
const functions = [foo, boo, baz];
runSequentially(functions).then((result) => {
}).catch((error) => {
});
- Q 承诺链接以正确的顺序做事
- 控制承诺执行顺序
- 不要在顺序链式承诺中包含 q 承诺结果
- AngularJS中承诺的顺序和时间
- 如何将嵌套承诺与Q连锁?我可以'Don’我不能让它们按正确的顺序运行
- 如何按顺序执行承诺数组
- 使用动态构建的 jQuery 承诺链按顺序激活特定元素
- 承诺回调的触发顺序是什么
- nodeJS中的承诺/承诺中的回调/执行顺序是不对的
- 从数组中按顺序执行一堆 WinJS 承诺
- 从顺序 jQuery ajax 调用返回承诺
- Angular JS:按顺序处理承诺(无链接)
- 承诺链不使用 Q 承诺库按顺序执行
- 如何使用承诺实现顺序异步计算
- AngularJS$q承诺成功的回调以错误的顺序执行
- Javascript承诺以相反的顺序加载
- 承诺的解决顺序是否与Promise.sexel中提到的顺序相同
- 链接HTTP帖子承诺角度不按顺序
- 我如何存储for循环的计数,承诺以任意顺序返回
- 传递值时的顺序承诺