JavaScript的执行
JavaScript 的执行
首先一个 js 脚本本身对于浏览器而言就是一个宏任务,也是第一个宏任务,而处于其中的代码可能有 3 种:非异步代码、产生微任务的异步代码(promise 等)、产生宏任务的异步代码(settimeout、setinterval 等)。 我们知道宏任务处于一个队列中,应当先执行完一个宏任务才会执行下一个宏任务,所以在 js 脚本中,会先执行非异步代码,再执行微任务代码,最后执行宏任务代码。这时候我们进行到了下一个宏任务中,又按照这个顺序执行。
需要注意的是:微任务总是先于宏任务这个说法不准确,应该是处于同一级的情况下才能这么说。实际上微任务永远是宏任务的一部分,它处于一个大的宏任务内。
执行
- 首先我们分析有多少个宏任务
- 在每个宏任务中,分析有多少个微任务;
- 根据调用次序,确定宏任务中的微任务执行次序;
- 根据宏任务的触发规则和调用次序,确定宏任务的执行次序;
- 确定整个顺序。
定义宏任务和微任务
我们把宿主发起(浏览器api)的任务称为宏观任务,把 JavaScript 引擎发起的任务称为微观任务。
宏任务和微任务的代码
- macro-task 大概包括:
- script(整体代码)
- setTimeout
- setInterval
- setImmediate
- I/O
- UI render
- micro-task 大概包括:
- process.nextTick
- Promise
- Async/Await(实际就是 promise)
- MutationObserver(html5 新特性)
例子一
function sleep(duration) { return new Promise(function (resolve, reject) { console.log("b"); setTimeout(resolve, duration); });}console.log("a");sleep(5000).then(() => console.log("c"));例子二
setTimeout(() => { console.log(1);});new Promise((res) => { console.log(3); res(2);}).then((val) => { console.log(val);});console.log(4);我们现在要实现一个红绿灯,把一个圆形 div 按照绿色 3 秒,黄色 1 秒,红色 2 秒循环改变背景色
function sleep(duration) { return new Promise(function (resolve) { setTimeout(resolve, duration); });}async function changeColor(duration, color) { document.getElementById("traffic-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();参考