Promise与setTimeOut

当同时存在PromisesetTimeOut时,它们的执行顺序是什么呢?

作为浏览器或者运行环境,在拿到开发者给的JavaScript的代码后,首先要传递给JavaScript引擎,让其执行。但是JavaScript的运行,往往需要时间,这时候就需要一个认知,一个JavaScript引擎会常驻内存,等待我们将代码或者函数传递给它。

es3及之后

在早期,JavaScript没有异步执行的概念,当传递代码时,往往是顺序执行宿主(浏览器)发起的任务。

es5之后,JavaScript引入了Promise,JavaScript可以发起任务,而不需要浏览器的安排。

这里浏览器发起的任务为宏观任务,JavaScript引擎发起的任务为微观任务。

宏观任务与微观任务

JavaScript引擎等待宿主分配宏观任务,在操作系统中,等待行为称为事件循环。

简单来讲就是“等待” - “执行”。这里省略了判断循环是否结束,宏观队列的问题。

1
2
3
4
while(TRUE){
r = wait();
execute(r);
}

每次的执行过程,就是一个宏观任务,事件的循环也可以称为宏观任务队列。
在宏观任务中,JavaScript会执行Promise异步代码。JavaScript要保证代码在宏观任务里执行,因此宏观任务包含一个微观任务队列。

有了宏观任务和微观任务,就可以实现JavaScript的引擎和宿主任务了。这里,Promise永远在队列尾部添加微观任务,setTimeOut等宿主API,则添加宏观任务。

Promise

Promise 是 JavaScript 语言提供的一种标准化的异步管理方式,它的总体思想是,需要进行 io、等待或者其它异步操作的函数,不返回真实结果,而返回一个“承诺”,函数的调用方可以在合适的时机,选择等待这个承诺兑现(通过 Promise 的 then 方法的回调)。

执行顺序分析:

  • 分析几个宏观任务
  • 确定每个宏观任务里有几个微观任务
  • 根据调用顺序,确定微观任务执行顺序
  • 确定宏观任务顺序
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
    setTimeout(()=>console.log("d"), 0)
var r = new Promise(function(resolve, reject){
resolve()
});
r.then(() => {
var begin = Date.now();
while(Date.now() - begin < 1000);
console.log("c1")
new Promise(function(resolve, reject){
resolve()
}).then(() => console.log("c2"))
});
// 这里就不难理解,当代码执行时,输出c1、c2、d

function sleep(duration) {
return new Promise(function(resolve, reject) {
console.log("b");
setTimeout(resolve,duration);
})
}
console.log("a");
sleep(5000).then(()=>console.log("c"));
// a,b,c

asyc/await

es6新引入的特性,其运行基础为Promise,asyc函数必须返回Promise,返回的Promise即为异步函数。

async 函数是一种特殊语法,特征是在 function 关键字之前加上 async 关键字,这样,就定义了一个 async 函数,我们可以在其中使用 await 来等待一个 Promise

其强大之处在于可以嵌套。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// 盒子绿三秒,黄1秒,红三秒
//<div id="light" style="background: #fff;width:10px;height:10px;"></div>
function sleep(duration){
return new Promise(function(resolve){
setTimeout(resolve, duration);
})
}
async function changeColor(duration,color){
document.getElementById("light").style.background = color;
await sleep(duration);

}
async function main(){
while(true){
await changeColor(3000,"green");
await changeColor(1000, "yellow");
await changeColor(2000, "red");
}
}
main()
------本文结束 感谢阅读------