对于javascript执行机制巩固

javascript执行机制

对于javascript执行机制巩固

  • 同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数;
  • 当指定的事情完成时,Event Table会将这个函数移入Event Queue;
  • 主线程内的任务执行完毕为空,会去Event Queue读取对应的函数,进入主线程执行;
  • 上述过程会不断重复,也就是常说的Event Loop(事件循环)。

怎么知道主线程执行栈为空?
js引擎存在monitoring process进程,会持续不断的检查主线程执行栈是否为空,一旦为空,就会去Event Queue那里检查是否有等待被调用的函数。

  1. 关于setTimeout(fn,ms):

    • List item
    • 即便主栈为空,0毫秒实际也达不到。根据HTML的标准,最低是4毫秒
  2. 关于setInterval(fn,ms):

    • etInterval函数是每过指定时间,会有fn进入Event Queue。一旦setInterval的回调函数fn执行时间超过了延迟时间ms,那么就看不出时间间隔了
  3. Promise与process.nextTick(callback) (node环境下的事件监听依赖libuv与前端环境不完全相同)

  4. 任务定义:

    • macro-task(宏任务):包括整体代码script,setTimeout,setInterval,I/O, UI rendering 等
    • micro-task(微任务):Promise,process.nextTick,Object.observe(已废弃), MutationObserver(html5新特性) 等
    • 不同类型的任务会进入对应的Event Queue,比如setTimeout和setInterval会进入相同的Event Queue

事件循环的顺序,决定js代码的执行顺序。进入整体代码(宏任务)后,开始第一次循环。接着执行所有的微任务。然后再次从宏任务开始,找到其中一个任务队列执行完毕,再执行所有的微任务。

setTimeout(function() {
    console.log('setTimeout');
})

new Promise(function(resolve) {
    console.log('promise');
}).then(function() {
    console.log('then');
})

console.log('console');
  • 代码作为宏任务,进入主线程,第一轮事件开始
  • 遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。
  • 遇到Promise
    • new Promise立即执行
    • then函数分发到微任务Event Queue
  • 遇到console.log(),立即执行
  • 整体代码script作为第一个宏任务执行结束。
  • 查看微任务,发现then在微任务Event Queue里面,执行
  • 第一轮事件循环结束。
  • 第二轮,从宏任务Event Queue开始
  • Event Queue中setTimeout对应的回调函数,立即执行
  • 结束

对于javascript执行机制巩固

最后

  1. javascript是一门单线程语言,不管是什么新框架新语法糖实现的所谓异步,其实都是用同步的方法去模拟的
  2. 事件循环Event Loop是js实现异步的一种方法,也是js的执行机制。

本文转载于https://juejin.im/post/59e85eebf265da430d571f89