一、JS是单线程的,但是为什么会有同步异步的存在呢?因为JS中有非常关键的一块,Event Loop。
Event Loop是一个程序结构,用于等待和发送消息和事件。
简单的说,就是在程序中(不一定是浏览器)中跑两个线程,一个负责程序本身的运行,作为主线程; 另一个负责主线程与其他线程的的通信,被称为“Event Loop 线程" 。 每当遇到异步的 setTimeOut ,setInterval 这些异步任务,交给 EventLoop 线程,然后自己往后运行,等到主线程运行完后,再去 Event Loop 线程拿结果。
二、JS的异步分为:宏任务和微任务
在JavaScript中,任务可以分为宏任务和微任务两种类型。宏任务是指需要在任务队列中排队执行的任务,而微任务是指在当前任务执行结束后立即执行的任务。
2.1 常见的宏任务
script(整体代码)、setTimeout、setInterval、setImmediate(Node.js独有)、I/O操作、UI渲染等。
2.2 常见的微任务
Promise.then()、MutationObserver、process.nextTick(Node.js独有)等。
2.3 简单的例子
console.log('1');
setTimeout(() => {
console.log('2');
Promise.resolve().then(() => {
console.log('3')
});
});
Promise.resolve().then(() => {
console.log('4')
});
console.log('5');
输出结果为:1 5 4 2 3
三、JS执行流程
1. 主线程读取JS代码,此时为同步环境,形容对应的堆和执行栈
2. 主线程遇到异步任务,会推给异步线程进行处理
3. 异步进程处理完毕,将对应的异步任务推入任务队列
4. 主线程查询任务队列,执行微任务,将其按照顺序执行,全部执行完毕
5. 主线程查询任务队列,执行宏任务,取的第一个宏任务,执行完毕
6. 重复以上4,5步骤
四、看你学会了没
Promise.resolve().then(() => {
console.log("1");
setTimeout(() => {
console.log("2")
}, 0)
})
setTimeout(() => {
console.log("3")
Promise.resolve().then(() => {
console.log("4")
})
}, 0)
console.log("5")
答案在下方☺
五、看看你做对了没
输出结果为:5 1 3 4 2