归纳JS执行过程的相关知识点
摘自winter老师,《重学前端》
感性认知
- 首先考虑一下我们是浏览器或Node,我们该如何使用JavaScript引擎
- 当拿到一段Js代码时,浏览器或 Node环境首先要做的就是:传递给Js引擎,并让其执行;
- 我们提供setTimeout这样的API,允许JavaScript在特定的时机执行
-
归纳:一个JS引擎会常驻于内存中,等待着我们(宿主)把JS代码或函数传递给它执行
宏观任务与微观任务
JS 引擎等待宿主环境分配宏观任务,在操作系统中,通常等待的行为都是一个事件循环,所以在Node术语中,也会把这个部分称为 事件循环
// An highlighted block
while(TRUE) {
r = wait();
execute(r);
}
我们可以看到,整个循环做的事情基本上就是反复 等待-执行的过程
Promise
Promise是JS提供的一种标准化的异步管理方式,它的总体思想是,需要进行I/O、等待或者其他异步操作的函数,不返回真实结果,而返回一个“承诺”,函数的调用方可以在合适的时机,选择等待这个承诺的兑现(通过Promise的 then 方法的回调)
// An highlighted block
var r = new Promise(function(resolve){
console.log("a");
resolve();
})
setTimeout(()=>console.log("d"),0)
r.then(() => console.log("c"));
console.log("b")
我们发现,不管执行顺序如何,d必定发生在c之后,因为
- Promise产生的是JS引擎内部的微任务
- setTimeout是浏览器API,它产生宏任务
异步执行顺序
新特性 async/await
async/await是ES2016新加入的特性,它提供了for、if等代码结构来编写异步的方式,运行时基础是Promise
- async必定返回Promise,我们把所有返回Promise的函数都可以认为是异步函数
- async是一种特殊语法,特征是在function关键字前加上async关键字,这样就定义了一个async函数,我们可以用await来等待一个Promise
- async的强大之处在于可以嵌套,我们在定义了一批原子操作的情况下,可以利用async函数组合出新的async函数
// An highlighted block
function sleep(duration){
return new Promise(function(resolve,reject){
setTimeout(resolve,duration)
})
}
async function foo(name){
await sleep(2000);
console.log(name);
}
async function foo2(){
await foo("a");
await foo("b");
}
小练习
实现一个红绿灯,把一个圆形div按照绿色3秒,黄色1秒,红色2秒循环改变背景色。
// An highlighted block
//JS 部分
var sleep = function(duration){
return new Promise(function(resolve,reject){
setTImeout(resolve,duration)
})
}
var changeColor =async function(duration,color){
document.getElementById("circle").style.background = color;
await sleep(duration);
}
async main = function(){
while(true){
await changeColor(3000,"green");
await changeColor(1000,"yellow");
await changeColor(2000,"red");
}
}
main();