js执行机制

js执行机制

js是单线程的。通过执行机制模拟实现”多线程“。

 

如何实现多线程?

 

从广义上,分为同步任务异步任务

同步任务指的是,在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务;

异步任务指的是,不进入主线程、而进入”任务队列“(tack queue)的任务,只有”任务队列“通知主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

  1. 同步和异步任务分别进入不同的执行场所,同步的进入主线程,异步的进入Event Table并注册函数
  2. 当Event Table中指定的事情完成时(比如delay,ajax),会将这个函数移入Event Queue。
  3. 主线程内的任务执行完毕为空,才回去Event Queue读取对应的函数,进入主线程执行。
  4. 上述过程会不断重复,也称为事件循环(Event Loop)。
  5. js引擎存在monitoring process进程,不断检查主线程执行栈是否为空,一旦为空,就去Event Queue那里检查是否有等待被调用的函数。

对任务更精细的定义,分为宏任务微任务

  macro-task(宏任务):包括整体代码script、setTimeout、setInterval

  micro-task(微任务):Promise、process.nextTick.

不同类型的任务会进入对应的Event Queue。

Promise与事件循环

Promise在初始化时,传入的函数时同步执行的,然后注册then回调。注册完之后,继续往下执行同步代码,在这之前,then的回调不会执行。同步代码执行完毕后,才会在事件循环中检测是否有可用的promise回调,如果有,那么执行,如果没有,继续下一个事件循环。

  1. 宏任务、微任务都是队列,一段代码执行时,会先执行宏任务中的同步代码。
  2. 进入第一轮事件循环的时候会把全部的js脚本当成一个宏任务来运行。
  3. 如果执行中遇到setTimeout之类的宏任务,那么就把这个setTimeout内部的函数推入【宏任务的队列】中,下一轮宏任务执行时调用。
  4. 如果执行中遇到promise.then()之类的微任务,就会推入到【当前宏任务的微任务队列】中,在本轮宏任务的同步代码都执行完成后,依次执行所有的微任务。
  5. 第一轮事件循环中当执行完全部的同步脚本以及微任务队列中的事件,这一轮事件循环就结束了,开始第二轮事件循环。
  6. 第二轮事件循环同理先执行同步脚本,遇到其他宏任务代码块继续追加到【宏任务的队列】,遇到微任务,就会推入到【当前宏任务的微任务队列】中,在本轮宏任务的同步代码都执行完成后,依次执行当前所有的微任务。
  7. 开始第三轮循环...

  总结:首次进入事件循环,会把整个js代码当作宏任务执行,执行所有同步脚本,遇到其他宏任务代码块继续追加到【宏任务的队列】,下一轮宏任务执行时调用,继续本轮宏任务代码执行,遇到微任务,推入到【当前宏任务的微任务队列】中,在本轮宏任务的同步代码都执行完成后,依次执行所有的微任务。

 

posted @ 2021-09-30 11:25  亦茫茫  阅读(59)  评论(0编辑  收藏  举报