为什么Promise链式调用then后第2、3次数据获取仍异步运行
问题原因分析
- 核心原因是:Promise链式调用的
then方法,只有当前一个then的回调函数返回一个Pending状态的Promise实例时,后续的then才会等待该Promise状态变更后再触发。你写的代码中前两个then回调都没有返回自定义Promise,所以链式调用没有等待内部的setTimeout异步任务完成。 - 具体执行逻辑拆解:
- 初始代码同步执行,依次打印
Start Program、Start Getting Data 1,创建Promise实例后注册3秒的setTimeout,主线程继续执行打印End Program - 3秒后第一个
setTimeout触发,打印Got Data 1,Promise状态变为fulfilled,触发第一个then回调 - 第一个
then同步执行打印Start Getting Data 2,然后注册第二个3秒的setTimeout,该回调没有返回任何值,默认返回状态为fulfilled的空Promise,所以第二个then会立刻触发,不需要等第二个setTimeout执行 - 第二个
then同步执行打印Start Getting Data 3,注册第三个3秒的setTimeout,同样没有返回Promise,链式调用结束 - 再等3秒左右,第二个和第三个
setTimeout几乎同时触发,先后打印Got Data 2、Got Data 3
- 初始代码同步执行,依次打印
正确实现串行异步的写法
如果要实现获取数据1完成后等3秒拿数据2,拿完数据2再等3秒拿数据3的串行效果,需要在每个then的回调里返回包裹了异步任务的新Promise:
console.log("Start Program") console.log("Start Getting Data 1") new Promise((succes) => { setTimeout(()=>{ console.log("Got Data 1") succes()},3000) } ).then(()=>{ // 返回新的Promise,下一个then会等待这个Promise resolve return new Promise((resolve) => { console.log("Start Getting Data 2") setTimeout(()=>{ console.log("Got Data 2") resolve() },3000) }) }).then(()=>{ return new Promise((resolve) => { console.log("Start Getting Data 3") setTimeout(()=>{ console.log("Got Data 3") resolve() },3000) }) }) console.log("End Program")
内容的提问来源于stack exchange,提问作者Daniel Olarte
相关产品推荐
相关产品推荐

