js运行机制
本文最后更新于:2022年3月30日 下午
JS 的单线程
JavaScript 的单线程,与它的用途有关。作为浏览器脚本语言,JavaScript 的主要用途是与用户互动,以及操作 DOM。这决定了它只能是单线程,保证执行任务的有序并避开复杂的同步问题。
EventLoop
- js 是单线程运行的
- 浏览器是多线程的
在代码执行的时候,通过将不同函数的执行上下文压入执行栈中来保证代码的有序执行。如果遇到了异步任务,js 引擎并不会一直等待其返回结果,而是会将这个事件的回调放入任务队列,继续执行执行栈中的其他任务。当执行栈清空后,再去任务队列读取异步函数的回调加入执行栈中执行。
事件循环
- js同一时间只能执行一个任务,在这期间可能推入多个执行上下文
- 执行同步函数
- 将异步函数将其回调分别加入宏任务队列和微任务队列
- 执行栈为空后(同步函数执行完),读取微任务队列执行
- 执行栈为空后,读取宏任务队列执行
- 执行栈为空后,如果该宏任务继续产生微任务则需要执行完新的微任务
- 执行完本轮任务
任务队列
异步任务通过任务队列来管理,任务被分为两类:微任务(micro task
)和宏任务(macro task
)
微任务(js引擎自己发起的任务)包括
process.nextTick
,promise.then
,catch
,finally
,MutationObserver
- NOTE:
nextTick
会提升到微任务队列的栈顶 - NOTE:遇到
await
时,对await
右侧进行计算,接着先去去执行async
外部的同步函数,后再回到async
函数中
- NOTE:
宏任务(宿主环境[浏览器,node]下发的任务)包括
setTimeout
,setInterval
,setImmediate
,I/O
操作 ,UI
渲染
面试题
```javascript
// 1
console.log(“script start”); // 1setTimeout(function () {
console.log("setTimeout"); // 4
}, 0);
Promise.resolve()
.then(function () { console.log("promise1"); //2 }) .then(function () { console.log("promise2"); //3 });
1. ```javascript // 2 console.log("1"); //1 setTimeout(function () { console.log("2"); // 5 process.nextTick(function () { console.log("3"); //7 }); new Promise(function (resolve) { console.log("4"); //6 resolve(); }).then(function () { console.log("5"); //8 }); }); process.nextTick(function () { console.log("6"); //3 }); new Promise(function (resolve) { console.log("7"); //2 resolve(); }).then(function () { console.log("8"); //4 }); setTimeout(function () { console.log("9"); //9 process.nextTick(function () { console.log("10"); //11 }); new Promise(function (resolve) { console.log("11"); //10 resolve(); }).then(function () { console.log("12"); }); //12 });
```javascript
// 3
async function async1() {console.log(1); //1 new Promise(() => { console.log(2); //2 }); Promise.resolve().then(() => { console.log("异步3"); //6 }); console.log("同步3"); //3
}
Promise.resolve().then(() => {
console.log(4); //5
});
setTimeout(() => {
console.log(5); //7
});
async1();
console.log(6); //4
1. ```javascript setTimeout(function () { console.log("定时器开始啦"); }); new Promise(function (resolve) { console.log("马上执行for循环啦"); for (var i = 0; i < 10000; i++) { i == 99 && resolve(); } }).then(function () { console.log("执行then函数啦"); }); console.log("代码执行结束"); // 马上执行for循环啦 // 代码执行结束 // 执行then函数啦 // 定时器开始啦
```javascript
setTimeout(function () {console.log("setTimeout");
});
new Promise(function (resolve) {
console.log("promise"); resolve();
}).then(function () {
console.log("then");
});
console.log(“console”);
// promise
// console
// then
// setTimeout1. ```javascript console.log("1"); setTimeout(function () { // console.log('2'); process.nextTick(function () { console.log("3"); }); new Promise(function (resolve) { // console.log('4'); resolve(); }).then(function () { console.log("5"); }); }); process.nextTick(function () { console.log("6"); }); new Promise(function (resolve) { console.log("7"); resolve(); }).then(function () { console.log("8"); }); setTimeout(function () { process.nextTick(function () { console.log("10"); }); new Promise(function (resolve) { resolve(); }).then(function () { console.log("12"); }); });
```javascript
setTimeout(() => {console.log(1);
}, 0);
Promise.resolve().then(() => {console.log(2);
});
console.log(3);// 3 2
// 11. ```javascript setTimeout(() => { console.log(1); }, 0); let a = new Promise((resolve) => { console.log(2); resolve(); }) .then(() => { console.log(3); }) .then(() => { console.log(4); }); console.log(5); // 2 5 3 4 // 1
```javascript
let a = new Promise((resolve) => {console.log(2); resolve();
}).then(() => {
console.log(5);
});
a.then(() => {console.log(3);
});
a.then(() => {console.log(4);
});
// 2 5 3 4
1. ```javascript new Promise((resolve, reject) => { console.log("promise1"); resolve(); }) .then(() => { console.log("then11"); new Promise((resolve, reject) => { console.log("promise2"); resolve(); }) .then(() => { console.log("then21"); }) .then(() => { console.log("then23"); }); }) .then(() => { console.log("then12"); }); // promise1,then11,promise2,then21,then12,then23
```javascript
new Promise((resolve, reject) => {console.log("promise1"); resolve();
})
.then(() => { console.log("then11"); return new Promise((resolve, reject) => { console.log("promise2"); resolve(); }) .then(() => { console.log("then21"); }) .then(() => { console.log("then23"); }); }) .then(() => { console.log("then12"); });
// promise1 then11 promise2 then21 then12 then23
1. ```javascript new Promise((resolve, reject) => { console.log("promise1"); resolve(); }) .then(() => { console.log("then11"); new Promise((resolve, reject) => { console.log("promise2"); resolve(); }) .then(() => { console.log("then21"); }) .then(() => { console.log("then23"); }); }) .then(() => { console.log("then12"); }); new Promise((resolve, reject) => { console.log("promise3"); resolve(); }).then(() => { console.log("then31"); }); //promise1 promise3 then11 promise2 then31 then21 then12 then23
```javascript
async function async1() {console.log("async1 start"); await async2(); console.log("async1 end");
}
async function async2() {
console.log("async2");
}
console.log(“script start”);
setTimeout(function () {
console.log("settimeout");
}, 0);
async1();
new Promise(function (resolve) {
console.log("promise1"); resolve();
}).then(function () {
console.log("promise2");
});
console.log(“script end”);// script start,async1 start,async2,promise1,script end,async1 end,promise2
// settimeout1. ```javascript async function async1() { console.log("async1 start"); // 2 await async2(); console.log("async1 end"); // 7 } async function async2() { console.log("async2"); // 3 } console.log("script start"); // 1 setTimeout(function () { console.log("settimeout"); }); async1(); new Promise(function (resolve) { console.log("promise1"); //4 resolve(); }).then(function () { console.log("promise2"); // 8 }); setImmediate(() => { console.log("setImmediate"); }); process.nextTick(() => { console.log("process"); // 6 }); console.log("script end"); // 5 //script start,async1 start,async2,promise1,script end,process,async1 end,promise2 //sttimeout,setImmediate