事件环

222 阅读2分钟

常见的异步操作

  • timer
  • Ajax
  • DOM的事件操作
  • Promise.then
  • Node读取文件

javascript执行过程

  1. 从上到下依次解释每一条js语句

  2. 若是同步任务,则压入一个栈(主线程);如果是异步任务,就放到一个任务队列里

  3. 开始执行栈里的同步任务,直到将栈里的所有任务都走完,此时栈清空了

  4. 回过头看异步队列里如果有异步任务完成了,就生成一个事件并注册回调,压入栈中

  5. 再返回第3步,直到异步队列都清空,程序运行结束

  6. 宏任务任务对垒和微任务任务队列外层有个事件环,将触发后事件压入栈中执行

示例

    setTimeout(function () {
        console.log(1);
        Promise.resolve().then(function () {
            console.log(2);
        });
    });
    setTimeout(function () {
        console.log(3);
    });
    Promise.resolve().then(function () {
        console.log(4);
    });
    console.log(5);


示例注解

  • 结果 5,4,1,2,3

  • 不妨我们试着分析一下为什么是这个结果,首先输出5,因为console.log(5)是同步代码,这没什么可说的。

    之后将前两个setTimeout和最后一个Promise放入异步队列,注意它们的区分,此时执行完了同步代码之后发现微任务和宏任务队列中都有代码,按浏览器的事件环机制,优先执行微任务,此时输出4。

    然后执行宏任务队列里的第一个setTimeout,输出1。

    此时,setTimeout中又有一个Promise,放入微任务队列。

    再次清空微任务队列,输出2。

    最后宏任务队列里还有最后一个setTimeout,输出3。

Node和浏览器区别

  • 浏览器事件环是运行完一个宏任务马上清空微任务队列。
  • Node事件环是清空完一个阶段的宏任务队列之后再清空微任务队列。

常见的宏任务和微任务

宏任务 微任务
setTimeout Promise的then方法
setInterval process.nextTick
setImmediate MutationObserver
MessageChannel