几分钟拿捏面试必考点——JS事件循环
前言
js为单线程,即v8在执行js的过程中,只有一个线程会工作,可以节约性能。
同步代码和异步代码
- 同步代码:不耗时执行的代码;
- 异步代码:需要耗时执行的
微任务和宏任务
- 微任务:promise.then(),process.nextTick(),MutationOvserver()
- 宏任务:script,setTimeout,setInterval,setImmediate,I/O,UI-rendering
进程和线程
- 进程:cpu运行指令和保存上下文所需的时间
- 线程:运行一段指令所需的时间
正文
首先介绍一下事件循环的执行步骤,再通过三个实例来实操
事件循环执行步骤:
从上往下执行:
- 执行同步代码(这属于是同步宏任务);
- 如果有异步代码将其压入宏任务队列中;
- 如果有微任务将其压入微任务队列中;
- 同步代码执行完毕后;
- 将微任务队列出队,依次执行所有的微任务;
- 微任务执行完毕,如果有需要就会渲染页面;
- 将宏任务队列出队,执行异步宏任务,也是开启下一次事件循环。
实例一
console.log(1);
new Promise((reslove, reject) => {
console.log(2);
reslove();
}).then(() => {
console.log(3);
}).then(() => {
console.log(4);
});
setTimeout(() => {
console.log(5);
})
console.log(6);
这里我用画图的形式来分析该事件循环结果:
所以结果为:
实例二
console.log(1);
new Promise((resolve, reject) => {
console.log(2);
resolve()
})
.then(() => {
console.log(3);
setTimeout(() => {
console.log(4);
}, 0)
})
setTimeout(() => {
console.log(5);
setTimeout(() => {
console.log(6);
}, 0)
}, 0)
console.log(7);
结果:
实例三
先介绍一下关于async
和await
的知识点:
let data = null;
function getData() {
setTimeout(() => {
data = [1, 2, 3];
}, 1000);
}
function another() {
console.log(data);
}
getData();
another();
上面的代码,执行结果为null
,因为setTimeout
为异步的,所以执行函数getData
时会被挂起,先执行函数another
,那么怎么才可以让结果为[1, 2, 3]
呢?
- 之前我们介绍过promise,这里我们可以通过promise去实现:
let data = null;
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
data = [1, 2, 3];
resolve();
}, 1000);
});
}
function another() {
console.log(data);
}
getData().then(() => {
another();
});
我们也可以使用async
实现,同样时要返回一个promise
对象,但是不用通过then
,而是通过await
:
let data = null;
function getData() {
return new Promise((resolve, reject) => {
setTimeout(() => {
data = [1, 2, 3];
resolve();
}, 1000);
});
}
function another() {
console.log(data);
}
async function foo() {
await getData();
another();
}
foo();
通过上面的代码可以知道函数前面有async
时,函数里面会先执行await
后面的代码,还有一个注意点!!! await
执行后会将后续的代码阻塞进微任务队列
给出最后一个例子
console.log('script start');
async function async1() {
await async2();// await 会将后续的代码阻塞进微任务队列
console.log('async1 end');
}
async function async2() {
console.log('async2 end');
}
async1();
setTimeout(function() {
console.log('setTimeout');
}, 0);
new Promise(function(resolve, reject) {
console.log('promise');
resolve()
})
.then(() => {
console.log('then1');
})
.then(() => {
console.log('then2');
})
console.log('script end');
结语
转载自:https://juejin.cn/post/7379818614361931786