美文网首页
事件循环机制

事件循环机制

作者: 再见噜噜班 | 来源:发表于2020-03-10 22:28 被阅读0次

Javascript是单线程执行的,出现异步时,并不会阻塞JS的执行,而是接着往下执行,等到异步结果返回时再处理。对于这些异步的执行任务,就依靠JS的事件循环机制,即EventLoop。
JS中的任务,可以分为宏任务(macrotask)和微任务(microtask)。这两种任务分别由两个队列来维护,这两个队列都遵循先进先出的机制。

  • 宏任务:整体代码main script,setTimeout,setInterval,I/O,UI交互事件,postMessage,MessageChannel,setImmediate(Node.js环境)
  • 微任务:Promise.then(),MutationObserver,process.nextTick(Node.js 环境)

具体的执行过程:

  1. 从宏任务队列中取出第一个任务开始执行(我的理解是整体代码是宏任务队列中的第一个任务)
  2. 执行过程中遇到微任务就把微任务添加到微任务队列,遇到宏任务就把宏任务添加到宏任务队列
  3. 宏任务执行完后,查看微任务队列,如果有任务,就按顺序执行微任务,知道执行完毕
  4. GUI 渲染;
  5. 从宏任务队列中取出下一个宏任务开始执行,回到第2步

让我们来看一道题,分析在注释中:

function promise1(){
    return new Promise((resolve)=>{
        console.log('async1 start')          //4.promise立即执行,输出async1 start
        promise2().then(()=>{                //6.回调函数添加到微任务,微1
            console.log('async1 end')        //13.微1执行,输出async1 end
            resolve()
        })
    })
}
function promise2() {
    return new Promise((resolve)=>{
        console.log('async2')               //5.promise立即执行,输出async2
        resolve()
    })
    
}
console.log("script start");                  //1.整体代码宏任务执行,输出script start
setTimeout(function () {                      //2.回调函数添加到宏任务队列,宏1
    console.log("settimeout");               //15.宏1执行,输出settimeout
});
promise1()                                    //3.执行函数promise1
new Promise(function (resolve) {
    console.log("promise1");                  //7.promise立即执行,输出promise1
    resolve();
}).then(function () {                         //8.回调函数加入微任务队列,微2
    console.log("promise2");                  //14.微2执行,输出promise2
});
setImmediate(()=>{                           //9.回调函数加入宏任务队列,宏2
    console.log("setImmediate")       //16.宏2执行,输出setImmediate
})
process.nextTick(()=>{                       //10.回调函数加入微任务队列,微3
    console.log("process")                   //12.process.nextTick优先级高于promise,微3执行,输出process
})
console.log('script end');                   //11.整体代码执行,输出script end 

过程解析:

  1. 宏任务队列中只有一个宏任务,就是整体代码,并开始执行,输出script start
  2. 遇到setTimeout,将回调函数添加到宏任务队列,即宏任务队列为[console.log("settimeout"),],继续向下执行
  3. 遇到promise1函数,promise1入栈
  4. promise1中,new Promise(fn)中的fn会立即执行,输出async1 start,继续执行
  5. 遇到promise2函数,promise2入栈
  6. 执行promise2函数体,new Promise(fn)中函数立即执行,输出async2,返回一个promise,promise2出栈,继续执行promise1
  7. promise2().then是微任务,回调函数加入微任务队列,即当前微任务队列[console.log('async1 end')],promise1出栈,继续执行主体代码
  8. new Promise(fn)中fn立即执行,输出promise1,then方法中的函数加入微任务队列,则当前微任务队列为[console.log('async1 end'),console.log("promise2")],继续向下执行
  9. setImmediate是宏任务,回调函数加入宏任务队列,即当前宏任务队列为[console.log("settimeout"),console.log("setImmediate")],继续向下执行
  10. process.nextTick是微任务,回调函数加入微任务队列,即当前微任务队列为[console.log('async1 end'),console.log("promise2"),console.log("process")],继续向下执行
  11. 主体代码执行,输出script end
  12. 当前宏任务执行完毕,查看微任务队列为[console.log('async1 end'),console.log("promise2"),console.log("process")]
  13. 因为process.nextTick优先级高于promise,所以先执行,输出process,然后执行其他两个微任务,先后输出async1 end,promise2
  14. 微任务队列清空后,查看宏任务队列,为[console.log("settimeout"),console.log("setImmediate")]
  15. setTimeout的优先级高于setImmediate,所以先取出setTimeout宏任务并执行,输出settimeout
  16. 当前宏任务执行完毕,查看微任务队列,没有微任务,则继续执行下一个宏任务,输出setImmediate
    所以执行结果是:script start,async1 start,async2,promise1,script end,process,async1 end,promise2,settimeout,setImmediate
    优先级:process.nextTick()>Promise.then()>setTimeout>setImmediate。

相关文章

  • 并发:事件循环 & asyncio

    1. 事件循环机制 1.1. 什么是事件循环 事件循环(Event Loop),即通过轮询方法监控事件; asyn...

  • 《浏览器工作原理与实践》学习笔记(四)

    消息队列和事件循环 要想在线程运行过程中,能接收并执行新的任务,就需要采用事件循环机制。 事件循环机制:相比于线性...

  • 事件循环机制

    同步任务和异步任务 同步任务 即可以立即执行的任务,例如 console.log() 打印一条日志、声明一个变量或...

  • 事件循环机制

    js是单线程的。浏览器: js执行线程:负责执行js代码 UI线程:负责UI展示,负责展示给用户看到的页面 js事...

  • 事件循环机制

    事件循环(evenloop) 事件循环机制是宿主环境提供的。js中处理异步,增加了任务队列的概念(你不知道的js中...

  • 事件循环机制

    静下心学了一波事件循环机制,好开心,我学会了,首先还是得感谢作者写的笔记特别详细 链接: http://www.c...

  • 事件循环机制

    Javascript是单线程执行的,出现异步时,并不会阻塞JS的执行,而是接着往下执行,等到异步结果返回时再处理。...

  • 事件循环机制

    JS 有个全局的函数执行栈,这是执行同步函数的地方 除了函数执行栈,还有一个事件队列,这是执行异步函数的地方 异步...

  • 事件循环机制

    想要了解javascript的事件循环机制,首先从基础概念出发;关于线程和进程 进程好比图中的工厂;有单独的的自己...

  • 事件循环机制

    JS中存在一个叫做执行栈的东西。JS的所有同步代码都在这里执行,当执行一个函数调用时,会创建一个新的执行环境并压到...

网友评论

      本文标题:事件循环机制

      本文链接:https://www.haomeiwen.com/subject/flhndhtx.html