Nodejs学习心得沉淀(四)——事件循环和调用栈

Nodejs学习心得沉淀(四)——事件循环

在这篇文章中,你会了解到

  • 宏队列微队列与宏任务微任务
  • event loop执行模型要点

注意,因为其它关于Event Loop的文章已经写的很好了,并且配有大量的实例(文末链接),因此本文中不会大量讲解事件循环的机制,只会将事件循环中的一些要点提出,让大家能够对事件循环有一个宏观层面的清晰认识。


注意:node在11版本之后的eventloop执行与浏览器一致了,在这之前浏览器和nodejs分别各有一套Event Loop

JavaScript有一个基于事件循环的并发模型,事件循环负责执行代码、收集和处理事件以及执行队列中的子任务。这个模型与其它语言中的模型截然不同,比如 C 和 Java,libuv这个库提供两个最重要的东西是事件循环和线程池,两者共同构建了异步非阻塞I/O模型。

一、libuv
  • libuv是一个高性能的,事件驱动的I/O库,并且提供了跨平台(如windows, linux)的API。
  • 它的核心工作是提供一个event-loop,还有基于I/O和其它事件通知的回调函数。
  • libuv会负责将来自操作系统的事件收集起来,或者监视其他来源的事件。
    伪代码表示如下
while there are still events to process:
    e = get the next event
    if there is a callback associated with e:
        call the callback

在这里插入图片描述
这是lilbuv内部的一个结构,事实上,为了理解Event Loop,我们并不需要对用C语言写的libuv有多么深入的了解,只需要知道其内部关于Event Loop的执行原理即可

二、宏队列微队列与宏任务微任务

在这里插入图片描述
该图展示的是libuv提供的事件循环中的六个阶段,从概念上,这六个阶段都可以分别看作是一个宏队列

  • timers阶段:这个阶段执行setTimeout和setInterval预定的callback
  • I/O callback阶段:执行除了close事件的callbacks、被timers设定的callbacks、s
  • etImmediate()设定的callbacks这些之外的callbacks
  • idle, prepare阶段:仅node内部使用
  • poll阶段:获取新的I/O事件,适当的条件下node将阻塞在这里
  • check阶段:执行setImmediate()设定的callbacks
  • close callbacks阶段:执行socket.on(‘close’, …)这些callbacks

在这里插入图片描述
而微任务队列就是穿插在宏队列之间执行的

宏任务包括: setTimeout、setInterval、 setImmediate、requestAnimation、IO、UI rendering
微任务包括: process.nextTick(Node)、Promise、Object.observe、MutationObserver

  • JavaScript代码执行的具体流程(可以看带你彻底弄懂事件循环

  • 有哪些是常见的宏任务,又有哪些是微任务

  • 什么是回调栈、回调队列,以及堆,里面存放的是什么?

  • 微任务是在宏任务之前先执行的

  • 如果在执行microtask的过程中,又产生了microtask,那么会加入到队列的末尾,也会在这个周期被调用执行(就是说依旧会在宏任务之前执行)

  • 特立独行的process.nextTick(),执行的优先级高于微任务,底于script脚本

  • 事件循环的几个特点(执行至完成、添加消息、零延迟、多个运行时互相通信)
    看[并发模型与事件循环](https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/EventLoop)这篇文章

  • 通过大量的实践去理解事件循环的原型原理(几乎每篇文章都会有)

参考杨浩老师的课程,我们用一个简单的栗子来看一下事件循环的内部调用机制

const eventLoop = {
    queue:[],

    init(){
        while(this.queue.length){
            var callback = this.queue.shift()
            callback()
        }

        setTimeout(this.init.bind(this),50)
    },

    add(callback){
        this.queue.push(callback)
    }
}


eventLoop.init();

setTimeout(()=>{
    eventLoop.add(
        function () {console.log(1)}
    )
},400)


setTimeout(()=>{
    eventLoop.add(
        function () {console.log(2)}
    )
},800)

感谢阅读,欢迎批评指正,希望大家能够在追求卓越中不断进步,让优秀成为一种习惯~

参考文章:

带你彻底弄懂Event Loop
node事件循环
并发模型与事件循环

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值