事件循环

147 阅读1分钟

术语

synchronous:同步任务、asynchronous:异步任务、task queue/callback queue:任务队列、execution context stack:执行栈、heap:堆、stack:栈、macro-task:宏任务、micro-task:微任务、Event Loop 事件循环

事件循环

  • 起因:因为 js 是单线程语言,当遇到异步任务(如 ajax 操作等)时,不可能一直等待异步完成,再继续往下执行,在这期间浏览器是空闲状态,显而易见这会导致巨大的资源浪费。

  • 解决方法:设定 Event Loop 规则为 javascript 的执行机制。通过执行机制解决上面问题

  • 执行流程:

    1. 所有任务都在主线程上执行,形成一个执行栈。
    2. 主线程之外,还存在一个"任务队列"(task queue)。只要发现异步任务就将其放入"任务队列"中
    3. 一旦"执行栈"中的所有同步任务执行完毕,系统就会读取"任务队列"。那些对应的异步任务,结束等待状态,进入执行栈并开始执行。
  • ps:

    1. promise 主体里的代码属于同步任务, .then()里的代码才属于微任务
      promise(
        console.log(1)   // 同步任务,按顺序执行
      ).then(res=>{
        console.log(res)   // 微任务
      })
    
    1. Async/Await Await 会导致其后面的代码成为微任务
      async function fn1(){
        console.log('1start')
        await fn2();
        console.log('1ending')
      }
    
      function fn2(){
        console.log('2start')
        console.log('2ending')
      }
      fn1();
    
      // 1start 2start 2ending 1ending
    

异步任务:宏任务(macro-task)和微任务(micro-task) 任务队列:宏任务队列和微任务队列

  • 不同的任务类型会依次进入自身对应的队列中,然后等待 Event Loop 将它们依次压入执行栈中执行。

  • macro-task 大概包括: script(整体代码) setTimeout setInterval setImmediate(node) I/O(node) UI render(node)

  • micro-task 大概包括: process.nextTick(node) Promise.then() Async/Await(实际就是 promise) MutationObserver(html5 新特性)