JS中Promise对象为什么能用同步的流程来表示异步的操作

369 阅读2分钟

举个例子,有一个需求是按序加载数据,加载完数据a,才能加载数据b,加载完数据b才能加载数据c,依次类推.....

先上需求代码

function requestA(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve("拿到的数据a");
        },3000)
    });
}
function requestB(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve("拿到的数据b");
        },2000)
    });
}
function requestB(){
    return new Promise(function(resolve,reject){
        setTimeout(function(){
            resolve("拿到的数据c");
        },1000)
    });
}

定时器用来模拟请求数据所需的时间。

再上解决代码

console.log("我是开头");
requestA().then((data)=>{
    console.log(data);
    return requestB();
}).then((data)=>{
    console.log(data);
    return requestC();
}).then((data)=>{
    console.log(data);
});
console.log("我是结尾");

Nodejs或者浏览器中的js环境都是先运行同步代码,碰见异步代码将其放进一个容器中,等待条件OK再执行(涉及到两种不同环境下js的Evenloop,这里只粗略涉及,详细内容在另一篇文章中)

就上面的简单情况而言,可以先这么简单理解: 先执行同步代码,再执行异步代码。

分析代码执行流程

1.遇到同步代码console.log("我是开头"),直接输出"我是开头"。

2.requestA()返回其对应的Promise对象,因为该对象内的代码是异步代码, 所以先将其放入异步容器中。返回的Promise对象中的resolve没有执行,所以后面的then方法也不执行。

3.遇到同步代码console.log("我是结尾"),

控制台输出

我是开头

我是结尾

4.等待三秒后,容器中的异步代码满足执行条件,执行resolve(),改变Promise对象状态为成功,执行第一个then()方法,

控制台输出

我是开头

我是结尾

拿到的数据a

5.返回requestB()所产生的Promise对象,继续执行第四步(把三秒改成两秒)

控制台输出

我是开头

我是结尾

拿到的数据a

拿到的数据b

6.返回requestB()所产生的Promise对象,继续执行第四步(把三秒改成一秒),流程执行完毕

最终控制台输出:

我是开头

我是结尾 (等待三秒)

拿到的数据a (等待两秒)

拿到的数据b (等待一秒)

拿到的数据c