资讯专栏INFORMATION COLUMN

理解Event-Loop

blair / 1820人阅读

摘要:回调函数任务完成的时候,需要执行哪段代码来处理呢当然是回调函数了。事件处理器和回调函数类似。但是特定的事件处理器在浏览器进入异步事件驱动阶段时就会针对特定的事件注册。当事件对象返回到执行线程时,事件处理器也会同时进入执行栈中执行。

Event Loop(事件轮询)机制是一个经常把人搞晕的东东。我不敢说我完全明白,只是在此谈谈我的浅见。

事件的处理

浏览器是一个事件驱动(event-driven)架构的软件。它的UI线程中会不断产生用户事件。但是处理事件的JavaScript是单线程执行的,这是一个浏览器环境下难以改变的现状(HTML5 Web Works没有从本质上改变这个模型)。这意味着:在JavaScript处理某个任务(执行某段代码)过程中,如果产生了用户事件,它不会立即被处理。那这种情况该怎么办呢?

浏览器维护了一个“任务队列”(一个优先队列数据结构),它是一个浏览器进程资源。每当UI线程产生一个事件,事件对象就被当做任务放入任务队列中(enqueue)。当JavaScript执行线程空闲的时候,队列中的一个任务就会被送往JavaScript执行线程(dequeue),进行相应的处理。

这个enqueue和dequeue的机制就是“Event Loop”。

但是,不仅用户事件可以被Event Loop机制处理,还能更多的东西是依赖这个机制的。

异步IO的处理

如果没有异步的理念,这个世界会完全不同:一个耗时的I/O操作(例如HTTP请求)会导致JavaScript执行线程等待,而后续的操作得不到执行。这种情况下,一个耗时的服务器端数据库操作http请求,会让JavaScript执行线程阻塞,浏览器将长期处于假死状态,在此期间,其他后续操作(包括用户的交互事件)得不到响应。

好在浏览器不是单线程的。它可以(但不是必须)让这些I/O任务让其他线程来托管,这样就形成了一个执行任务的线程池。但是这些任务的结果总归要回到JavaScript执行线程上处理,于是这些任务也被放到任务队列中:需要被托管的任务被放入队列中(enqueue),已完成的任务会被从队列中一个个取出(dequeue),回到JavaScript执行线程执行回调。在这些耗时的I/O任务被托管的时候,JavaScript执行线程可以执行其他代码。

在Node中,这个过程是类似的。本文不表。

这便是异步的原理了。我们看到它同样依赖Event Loop的机制。

定时器

浏览器的全局对象window提供了两个方法,setTimeout和setInterval。这两个方法其实是调用了浏览器的API,将一个任务移除出JavaScript执行线程中,延时处理。

我们现在马上可以反应过来:这个将要被延时的任务同样是放到了任务队列中。在一次Event Loop过程中,它会优先将该时间点下已经到时的延时任务移除出队列,放入JavaScript执行线程中。这意味着,任务队列是一个优先队列。

但是由于JavaScript执行线程的执行时间是不确定的,所以这个延时只是一个大体的值,它取决于JavaScript执行线程的执行时间。

回调函数

任务完成的时候,JavaScript需要执行哪段代码来处理呢?当然是回调函数了。

但是不免奇怪的一点就是:JavaScript中怎么知道要执行的是哪个回调函数呢?答案就是:任务被放入任务队列的时候,该任务的回调函数会被注册(注册到什么地方?需要进一步探究)。这样,当特定任务完成的时候,任务结果和回调标记会返回给JavaScript执行线程,进入执行栈。

事件处理器

与其他任务不同,事件并不是由JavaScript执行线程发出的,而是从UI线程中发出的。

事件处理器和回调函数类似。但是特定的事件处理器在浏览器进入异步事件驱动阶段时就会针对特定的事件注册。当事件对象返回到JavaScript执行线程时,事件处理器也会同时进入执行栈中执行。

结束

越往后写,越发现我之前的一些理解有偏差。在学习过程中,我也要多反思,多总结。之前写的不对的地方,我也会尽早纠正。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/90859.html

相关文章

  • 结合microtask和macrotask理解event-loop

    摘要:讲的很清晰,看完之后更深一步的理解了事件循环机制。简短的概述下总结是一个宏任务源,写在里面的回调函数会加到宏任务队列中。至此,一轮的事件循环已经执行完毕,开启新的一轮事件循环。这就是整段代码执行情况的理解。 这篇文章真的是好文。讲的很清晰,看完之后更深一步的理解了事件循环机制。 http://www.jianshu.com/p/12b9... 简短的概述下总结 setTimeout是一...

    sarva 评论0 收藏0
  • 彻底搞懂浏览器Event-loop

    摘要:检查宏任务队列,发现有的回调函数立即执行回调函数输出。接着遇到它的作用是在后将回调函数放到宏任务队列中这个任务在再下一次的事件循环中执行。 为什么会写这篇博文呢? 前段时间,和头条的小伙伴聊天问头条面试前端会问哪些问题,他称如果是他面试的话,event-loop肯定是要问的。那天聊了蛮多,event-loop算是给我留下了很深的印象,原因很简单,因为之前我从未深入了解过,如果是面试的时...

    source 评论0 收藏0
  • Event-loop事件循环

    摘要:事件循环首先来看一段代码运行结果是先输出,然后大概好几秒大于一秒以后依次输出,。原因就在以下这部分代码中原因就是这部分循环的代码执行过程超过了秒。而这个循环是放在里面的。 Event-loop 事件循环 首先来看一段代码 function fn(){ console.log(1) setTimeout(() => { console.log(2) }, 1000) ...

    MingjunYang 评论0 收藏0
  • 微任务、宏任务与Event-Loop

    摘要:所以本来快轮到你来办理业务,会因为老大爷临时添加的理财业务而往后推。在执行完同步代码与微任务以后,这时继续向后查找有木有宏任务。所以输出了第二次,等到这两次都执行完毕后才会去检查有没有微任务有没有宏任务。 首先,JavaScript是一个单线程的脚本语言。 所以就是说在一行代码执行的过程中,必然不会存在同时执行的另一行代码,就像使用alert()以后进行疯狂console.log,如...

    Nekron 评论0 收藏0

发表评论

0条评论

blair

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<