阅读 771

一道题引发的EventLoop思考

题目背景

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'); 
复制代码

题目的本质,是考察setTimeoutpromiseasync await的实现顺序及JS的时间循环方面的相关问题。

结果为: script start async1 start async2 promise1 script end async1 end promise2 settimeout

这里涉及到同步异步MicrotasksMacrotasksMicrotasks优先级别高于Macrotasks 其中MicrotasksMacrotasks分别是:

microtasks:

  • process.nextTick
  • promise
  • Object.observe
  • MutationObserver

macrotasks:

  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI渲染
  1. 一个事件循环(event loop)会有一个或多个任务队列(task queue)
  2. task queue 就是 macrotask queue
  3. 每一个 event loop 都有一个 microtask queue
  4. task queue == macrotask queue != microtask queue
  5. 一个任务 task 可以放入 macrotask queue 也可以放入 microtask queue 中

因此事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。

定时器是怎么实现定时的?为什么会出现不定时的情况?

首先,要明确的一点:javascript是以单线程的方式运行的。JavaScript的主要用途是与用户互动,以及操作DOM。若以多线程的方式,则可能出现冲突。假设有两个线程同时操作一个DOM元素,线程1要求浏览器删除DOM,而线程2却要求修改DOM样式,这时浏览器就无法决定采用哪个线程的操作。当然,我们可以为浏览器引入“锁”的机制来解决这些冲突,但大大提高复杂性,所以 JavaScript从诞生开始就选择了单线程执行。在某一时刻内只能执行特定的一个任务,并且会阻塞其它任务执行。 但是JavaScript 有个基于“Event Loop”并发的模型(不是并行)。前者是逻辑上的同时发生,而后者是物理上的同时发生。所以,单核处理器也能实现并发。 上图说明一下并发和并行:

占用

小tips:

console.log(1);
setTimeout(function(){
    console.log(2);
    Promise.resolve(1).then(function(){
        console.log('ok')
    })
})
setTimeout(function(){
    console.log(3)
})
复制代码

分析:先默认走栈,输出1。此时并没有微任务,所以微任务不会执行。先走第一个setTimeout,输出2,同时将微任务放到队列中,执行微任务,输出ok,微任务执行完,再走宏任务,输出3。

Node.js的Event Loop

V8引擎解析JavaScript脚本。 解析后的代码,调用Node API。 libuv库负责Node API的执行。它将不同的任务分配给不同的线程,形成一个Event Loop(事件循环),以异步的方式将任务的执行结果返回给V8引擎。 V8引擎再将结果返回给用户。

浅谈event loop

关注下面的标签,发现更多相似文章
评论