JS的事件循环(Event Loop)

说明:

Javascript是一门非阻塞单线程脚本语言;

浏览器是多进程的,系统给它的进程分配了资源(CPU、内存),打开Chrome会有一个主进程,每打开一个Tab页就有一个独立的进程;

JavaScript的任务分为同步任务和异步任务,所有的同步任务都会进入到主执行栈(形成一个执行栈execution context stack),等待任务的回调结果进入一种任务队列(task queue),直到主执行栈的任务执行完毕才会执行任务队列的异步任务,异步任务会塞入主执行栈,异步任务执行完毕后会再次进入下一个循环,整个执行过程,我们称为事件循环过程。任务队列又分为macro-task(宏任务)与micro-task(微任务),在最新标准中,它们被分别称为task与jobs。

macro-task大概包括:

  • script(整体代码)
  • setTimeout
  • setInterval
  • setImmediate
  • I/O
  • UI render

micro-task大概包括:

  • process.nextTick
  • Promise
  • Async/Await(实际就是promise)
  • MutationObserver(html5新特性)

整体执行流程图:

async/await执行顺序注意:

输出:script start => async2 end => Promise => script end => promise1 => promise2 => async1 end => setTimeout

分析这段代码:

  1. 执行代码,输出script start
  2. 执行async1(),会调用async2(),然后输出async2 end,此时将会保留async1函数的上下文,然后跳出async1函数。
  3. 遇到setTimeout,产生一个宏任务
  4. 执行Promise,输出Promise。遇到then,产生第一个微任务
  5. 继续执行代码,输出script end
  6. 代码逻辑执行完毕(当前宏任务执行完毕),开始执行当前宏任务产生的微任务队列,输出promise1,该微任务遇到then,产生一个新的微任务
  7. 执行产生的微任务,输出promise2,当前微任务队列执行完毕。执行权回到async1
  8. 执行await,实际上会产生一个promise返回,即 let promise_ = newPromise((resolve,reject){ resolve(undefined)})
  9. 执行完成,执行await后面的语句,输出async1 end
  10. 最后,执行下一个宏任务,即执行setTimeout,输出setTimeout

新版的chrome浏览器中不是如上打印的,因为chrome优化了,await变得更快了,输出为:

而await后面跟的是一个异步函数的调用,比如上面的代码,将代码改成这样:

 输出:script start => async2 end => Promise => script end => async1 end => promise1 => promise2 => async1 end setTimeout

 未写完,后续待更新...

猜你喜欢

转载自www.cnblogs.com/babyfacer/p/12306026.html