如何让Promise.all按预期执行我的Promise实例?
理解Promise.all的工作原理
我太懂这种感觉了——Promise.all看起来明明应该很简单,但实际写代码的时候总容易卡壳,尤其是刚摸异步编程的时候。先帮你把没写完的代码补完整,再一步步拆解它的工作逻辑。
首先,先补全你的代码(假设第二个Promise和第一个逻辑类似):
const getFirstPromise = function() { return new Promise((resolve, reject) => { setTimeout(function(){ console.log("1"); resolve("First!"); // Yay! Everything went well! }, 2500); }); }; const getSecondPromise = function() { return new Promise((resolve, reject) => { setTimeout(function(){ console.log("2"); resolve("Second!"); }, 1500); }); }; // 用Promise.all调用两个Promise Promise.all([getFirstPromise(), getSecondPromise()]) .then(results => { console.log("All done!", results); }) .catch(error => { console.error("Something failed:", error); });
核心工作逻辑拆解
先给你划几个Promise.all的关键知识点:
- 它接收一个可迭代对象(最常用的就是Promise数组),会让所有传入的Promise并行启动执行
- 只有当所有Promise都成功
resolve时,它才会进入then回调,返回的结果是一个数组——数组的顺序和你传入Promise的顺序完全一致,不管它们实际resolve的先后 - 只要有一个Promise失败
reject,它会立刻触发catch回调,返回第一个reject的错误原因,不会再等其他Promise完成
看这段代码的实际执行流程
当你运行这段代码时:
- 调用
getFirstPromise()和getSecondPromise()的瞬间,两个setTimeout就已经启动了——这就是“并行执行”的意思,它们各自走自己的异步流程,互不等待 - 1.5秒后,第二个Promise的超时结束,输出
2,并resolve为"Second!" - 再过1秒(总共2.5秒),第一个Promise的超时结束,输出
1,并resolve为"First!" - 此时所有Promise都完成了,
then回调触发,输出All done! ["First!", "Second!"]——注意结果数组里第一个元素是第一个Promise的结果,第二个是第二个的,和它们resolve的时间无关
常见误区避坑
误区1:Promise.all是按顺序执行Promise?
完全不是!所有Promise在你传入Promise.all之前就已经开始执行了,Promise.all只是一个“等待器”,等所有任务都跑完而已。如果你需要按顺序执行异步任务,那Promise.all不是正确的选择,应该用链式then或者for...of循环。
误区2:有一个Promise reject,其他任务会停止?
不会!Promise.all只是立刻返回reject结果,但已经启动的异步操作会继续执行。比如我们改一下代码,让第二个Promise失败:
const getFailedPromise = function() { return new Promise((resolve, reject) => { setTimeout(function(){ console.log("3"); reject(new Error("Oops! Something went wrong")); }, 2000); }); }; Promise.all([getFirstPromise(), getFailedPromise()]) .then(results => { console.log("All done!", results); }) .catch(error => { console.error("Something failed:", error.message); });
运行后你会看到:
- 2秒后输出
3,同时触发catch,输出Something failed: Oops! Something went wrong - 再过0.5秒,第一个Promise的超时结束,还是会输出
1——因为它的异步任务已经启动了,不会被Promise.all的reject中断
内容的提问来源于stack exchange,提问作者Tad Donaghe
相关产品推荐
相关产品推荐

