JavaScript 事件循环机制 event loop

同步任务、异步任务

JavaScript是一门单线程语言,分为同步任务和异步任务

同步任务

在主线程上排队执行的任务,只有前一个任务执行完毕,才能继续执行下一个任务。

异步任务

  • 不进入主线程、而进入"任务队列"的任务
  • 只有等主线程任务全部执行完毕,"任务队列"的任务才会进入主线程执行。
  • 异步任务分为宏任务和微任务
  • 宏任务:宿主(Node、浏览器)发起的,会触发新一轮Tick的事件
    • 比如:script (可以理解为外层同步代码)、定时器回调、UI rendering/UI事件、postMessage,MessageChannel 、setImmediate,I/O(Node.js)、DOM 事件回调、ajax 回调
  • 微任务:JS引擎发起的事件
    • 比如:promise的回调、MutationObserver 的回调、object.observe(已废弃;Proxy 对象替代) 4. process.nextTick(Node.js)
  • 宏队列、微队列:js 中用来存储待执行回调函数的队列包含 2 个不同特定的列队
    • 宏队列:用来保存待执行的宏任务(回调)
    • 微队列:用来保存待执行的微任务(回调)

执行顺序(即事件循环)

JavaScript 事件循环机制 event loop_第1张图片

  1. 先执行所有同步任务,碰到异步任务放到任务队列中
  2. 同步任务执行完毕,开始执行当前所有的异步任务
  3. 先执行微队列里面所有的微任务
    1. 设置进入微任务检查点的标志为true。
    2. 当事件循环的微队列不为空时:
      1. 选择一个最先进入microtask队列的microtask;
      2. 设置事件循环的当前运行任务为已选择的microtask;
      3. 运行microtask;
      4. 设置事件循环的当前运行任务为null;
      5. 将运行结束 的microtask从microtask队列中移除。
    3. 对于相应事件循环的每个环境设置对象(environment settings object),通知它们哪些promise为 rejected。
    4. 清理indexedDB的事务。
    5. 设置进入microtask检查点的标志为false。
    6. 更新界面渲染。
  4. 然后执行一个宏任务,如果没有宏任务可以选择,则会 跳转至微任务的执行步骤。
    1. 将事件循环的当前运行宏任务设置为已选择的宏任务。
    2. 运行宏任务。
    3. 将事件循环的当前运行任务设置为null。
    4. 将运行完的宏任务从宏任务队列中移除。
  5. 然后再执行所有的微任务
  6. 再执行一个宏任务,再执行所有的微任务·······依次类推到执行结束。

当前执行栈执行完毕时会立刻先处理所有微任务队列中的事件, 然后再去宏任务队列中取出一个 事件。同一次事件循环中, 微任务永远在宏任务之前执行。

你可能感兴趣的:(JavaScript基础,javascript,开发语言,ecmascript)