• 朝阳消防联合快递行业开展消防安全宣传培训系列活动 2019-04-05
  • 期待已久的桃花运 竟然可以穿出来?! ——凤凰网房产广州 2019-04-05
  • 中关村雍和航星科技园,北京中关村雍和航星科技园 2019-03-22
  • 潇湘玉竹版主辛苦了! 2019-02-13
  • 端午新经济体验无处不在 “指尖端午”玩出新花样 2019-02-13
  • 工信部:鼓励婴幼儿配方乳企质量安全追溯体系建设 2018-12-30
  • "说说 Event Loop 最近浏览了很多前端的面试题,发现绝大多数题目里都有问到 Event Loop。正好我收集整理了部分相关的信息,于是也来说说我理解的 Event Loop。 从单线程说起 为什么会有 Event Loop?这就要从 Javascript 的特点“单线程”开始说起了。 单线程是什么?意思就是在一 .."

    说说 Event Loop

    本贴最后更新于 387 天前,其中的信息可能已经时移世改

    说说 Event Loop

    最近浏览了很多前端的面试题,发现绝大多数题目里都有问到 Event Loop。正好我收集整理了部分相关的信息,于是也来说说我理解的 Event Loop。

    从单线程说起

    为什么会有 Event Loop?这就要从 Javascript 的特点“单线程”开始说起了。 单线程是什么?意思就是在一个时间内程序只能做一件事。很多人都用过 Java 或者 C++ 之类的语言,肯定能体会到这些语言的多线程带来的很多便捷性。然而,Javascript 在设计之初的定位是用来处理用户交互以及操作 DOM,如果 Javascript 也设计成多线程,势必会带来很复杂的同步问题。

    既是单线程又是异步

    单线程的 JS 中,所有的任务都要排队,只有等前一个任务执行完毕才会执行后一个任务。 那所谓的异步又是怎么回事呢? 在单线程的 Javascript 中,涉及到大 IO 操作的任务,我们都可以为其注册回调函数:当程序执行到 IO 操作时,主线程将这个操作挂起,继续执行接下来的操作。等到 IO 操作完成之后,再将挂起的任务继续执行下去。 这个注册了回调函数的任务,我们可以叫它“异步任务”。

    任务队列 (EventQueue)

    任务队列是一个队列,具有先进先出的特点。也就是说,先被加入任务队列的任务,会优先被主线程读取。 当一个异步任务完成之后,JS 就会触发某一指定事件 (比如说 onload, onerror),则其所指向的函数 (回调函数) 就会被加入到任务队列中。 可以尝试理解以下代码。

    const img = document.createElement('img')
    img.src = 'https://image.hduzplus.xyz/image/1507523489652.jpg'
    img.onload = function() { 
      console.log(1)
    }
    const timeoutFunc = function() {
      console.log(3)
    }
    setTimeout(timeoutFunc, 0)
    console.log(2)
    
    // 执行结果:2 3 1
    

    异步任务和同步任务

    在 JS 中,任务分为两种,一种是上文提到的异步任务,另一种是同步任务。 同步任务意思就是在主线程上依此执行的任务。 异步任务就是进入任务队列的任务。只有等其执行完毕,任务队列通知主线程后,这个异步任务才会进入到主线程执行。

    异步执行机制

    1. 所有的同步任务在主线程上依此执行;
    2. 异步任务执行完成后,相应事件的回调函数被加入到任务队列中;
    3. 主线程上的同步任务执行完毕后,将任务队列内的任务依此移入主线程执行;
    4. 重复以上 3 步。
    // 伪代码
    while(true) {
      // 执行主线程操作
      while(p = eventQueue.out()) {
        // process p
      }
    }
    

    Event Loop

    主线程循环的从异步队列中读取事件,这个过程其实就是 Event Loop。 接下来可以看之前的代码。 主线程顺序执行,遇到异步任务则将其挂起,等待异步任务执行完成后再将其回调加入主线程。 所以先输出主线程中的’2’ 图片 load 事件比 setTimeout 事件执行的慢,所以 setTimeout 的回调被先加入任务队列。所以输出’3’ 最后输出’1’

    扩展:异步任务是如何在单线程中执行的?

    事实上,JS 的单线程指的是语言层面的单线程。在浏览器中我们执行某个 ajax 异步操作,这项异步操作是由浏览器完成的。我们注册的回调函数,实际上是向浏览器提交了这个回调函数。当异步操作完成之后,浏览器将该回调函数传入到执行上下文中的任务队列内。

    • B3log

      B3log 是一个开源组织,名字来源于“Bulletin Board Blog”缩写,目标是将独立博客与论坛结合,形成一种新的网络社区体验,详细请看 B3log 构思。目前 B3log 已经开源了多款产品:Pipe、Solo、Sym、 Wide 等,欢迎大家加入,贡献开源。

      2429 引用 ? 3804 回帖 ? 623 关注
    • 研究
      10 引用 ? 27 回帖
    • 前端

      前端技术一般分为前端设计和前端开发,前端设计可以理解为网站的视觉设计,前端开发则是网站的前台代码实现,包括 HTML、CSS 以及 JavaScript 等。

      162 引用 ? 1180 回帖
    感谢    关注    收藏    赞同    反对    举报    分享
    8 回帖    
    请输入回帖内容...
    • kafuly ?    

      很腻害 (^U^) ノ ~YO

      感谢    赞同    反对    举报    分享       评论    回复
    • cbam ?      

      牛逼啊

      感谢    赞同    反对    举报    分享       评论    回复
    • xjtushilei ?      

      学习了

      感谢    赞同    反对    举报    分享       评论    回复
    • salamander ?   1 感谢      

      道理不难,异步任务的执行应该是开了一个进程去做的,执行完后把 callback 放入任务队列,js 执行栈空闲去看看任务队列有没有 callback,有的话执行这个 callback Nodejs 也是这个原理,天生的异步非阻塞,但这个模式不适合 CPU 密集型的任务,因为执行栈一旦阻塞,别的什么的就全阻塞了

      感谢    赞同    反对    举报    分享       评论    回复
    • Vanessa ?      

      是的。我还去一峰大哥那里看了看

      感谢    赞同    反对    举报    分享       评论    回复
    • zjhch123 ? API ?      

      哈哈,要是没有一峰大哥,我肯定没有现在这点实力 ~

      1 回复 
      感谢    赞同    反对    举报    分享       评论    回复
    • Vanessa ?            

      启蒙老师呀。

      感谢    赞同    反对    举报    分享       评论    回复
    • QuincySx ?      

      与 Android 的 Handler 机制有点像

      感谢    赞同    反对    举报    分享       评论    回复
    请输入回帖内容...
  • 朝阳消防联合快递行业开展消防安全宣传培训系列活动 2019-04-05
  • 期待已久的桃花运 竟然可以穿出来?! ——凤凰网房产广州 2019-04-05
  • 中关村雍和航星科技园,北京中关村雍和航星科技园 2019-03-22
  • 潇湘玉竹版主辛苦了! 2019-02-13
  • 端午新经济体验无处不在 “指尖端午”玩出新花样 2019-02-13
  • 工信部:鼓励婴幼儿配方乳企质量安全追溯体系建设 2018-12-30