EventLoop
JavaScript是一种单线程语言,所有任务都在一个线程上完成。即代码执行是同步并且阻塞的。
Event Loop 就是为了确保异步代码可以在同步代码执行后继续执行的Event Loop即事件循环,指浏览器或者node执行环境下的一种解决JavaScript单线程运行时不会发生阻塞的一种机制。也是我们常说的异步执行的原理。
Wikipedia对Event Loop的定义
a programming construct that waits for and dispatches events or messages in a program.(在程序中等待和分发事件或消息的一种编程结构)
为什么要懂Event Loop
- 增加自己的技术深度,增加编程知识储备,了解JavaScript的运行机制。
- 公司面试经常会问到JavaScript的运行机制,了解原理,以不变应万变、
同步和异步
- 同步
如果在代码返回结果的时候,调用者能够拿到预期的结果,那么这段代码就是同步的。 - 异步
JavaScript中请求ajax,发送promise,还有定时器,async+await等,在调用后不能立即得到预期的结果,而是在将来才能得到,这就是异步。
事件循环
- 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数
- 当指定的事情完成时,Event Table会将这个函数移入Event Queue。
- 等待同步代码执行完毕后,会去Event Queue读取对应的函数,进入主线程执行。
- 上面的过程会不断循环重复循环,这就是事件循环。
调用栈
JavaScript 有一个 main thread 主线程和 call-stack 调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。
JavaScript 调用栈采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空。
宏任务、微任务
在JavaScript中,任务被分为两种,一种宏任务(Macro Task)也叫Task,一种叫微任务(Micro Task)。
- 宏任务
宿主发起的任务为宏任务
宏任务主要包含:setTimeout、setInterval、script(整体代码)、I/O、UI 交互事件、setImmediate(Node.js 环境) - JavaScript引擎发起的任务为微任务
微任务主要包括:Promise、MutaionObserver、process.nextTick(Node.js 环境)、object.observe,async关键字会将任务转为微任务。
每个宏任务中又包含一个微任务队列
异步执行的方法
- 分析有多少个宏任务
- 在每个宏任务中,分析有多少个微任务
- 根据调用次序,确定宏任务中微任务执行次序
- 根据宏任务调用次序和触发原则,确定宏任务执行次序
- 确定整个次序
规范:先执行微任务,再执行宏任务
在这里插入代码片window.console.log("1");
async function test() {
return Promise.resolve("4444"); // 如果返回值是字符串 执行顺序是15432
} // 如果返回promise 执行顺序是15342
async function testAsync() {
const a1 = await test();
console.log(a1);
}
testAsync();
Promise.resolve().then(() => {
console.log("333");
});
setTimeout(() => {
console.log("22");
}, 0);
window.console.log("55555");
上面代码执行顺序是先执行同步任务,异步任务放入队列中,同步任务执行完之后返回执行异步任务,异步任务又分宏任务和微任务,先执行微任务,再执行宏任务,JavaScript的执行机制也是这样。
最后:
- JavaScript是一门单线程语言
- Event Loop是JavaScript的执行机制