Event Loop(事件轮询)机制是一个常常把人搞晕的东东。我不敢说我彻底明白,只是在此谈谈个人浅见。数据库
浏览器是一个事件驱动(event-driven)架构的软件。它的UI线程中会不断产生用户事件。可是处理事件的JavaScript是单线程执行的,这是一个浏览器环境下难以改变的现状(HTML5 Web Works没有从本质上改变这个模型)。这意味着:在JavaScript处理某个任务(执行某段代码)过程当中,若是产生了用户事件,它不会当即被处理。那这种状况该怎么办呢?浏览器
浏览器维护了一个“任务队列”(一个优先队列数据结构),它是一个浏览器进程资源。每当UI线程产生一个事件,事件对象就被当作任务放入任务队列中(enqueue)。当JavaScript执行线程空闲的时候,队列中的一个任务就会被送往JavaScript执行线程(dequeue),进行相应的处理。服务器
这个enqueue和dequeue的机制就是“Event Loop”。数据结构
可是,不只用户事件能够被Event Loop机制处理,还能更多的东西是依赖这个机制的。架构
<!--more-->异步
若是没有异步的理念,这个世界会彻底不一样:一个耗时的I/O操做(例如HTTP请求)会致使JavaScript执行线程等待,然后续的操做得不到执行。这种状况下,一个耗时的服务器端数据库操做http请求,会让JavaScript执行线程阻塞,浏览器将长期处于假死状态,在此期间,其余后续操做(包括用户的交互事件)得不到响应。函数
好在浏览器不是单线程的。它能够(但不是必须)让这些I/O任务让其余线程来托管,这样就造成了一个执行任务的线程池。可是这些任务的结果总归要回到JavaScript执行线程上处理,因而这些任务也被放到任务队列中:须要被托管的任务被放入队列中(enqueue),已完成的任务会被从队列中一个个取出(dequeue),回到JavaScript执行线程执行回调。在这些耗时的I/O任务被托管的时候,JavaScript执行线程能够执行其余代码。oop
在Node中,这个过程是相似的。本文不表。学习
这即是异步的原理了。咱们看到它一样依赖Event Loop的机制。线程
浏览器的全局对象window提供了两个方法,setTimeout和setInterval。这两个方法实际上是调用了浏览器的API,将一个任务移除出JavaScript执行线程中,延时处理。
咱们如今立刻能够反应过来:这个将要被延时的任务一样是放到了任务队列中。在一次Event Loop过程当中,它会优先将该时间点下已经到时的延时任务移除出队列,放入JavaScript执行线程中。这意味着,任务队列是一个优先队列。
可是因为JavaScript执行线程的执行时间是不肯定的,因此这个延时只是一个大致的值,它取决于JavaScript执行线程的执行时间。
任务完成的时候,JavaScript须要执行哪段代码来处理呢?固然是回调函数了。
可是难免奇怪的一点就是:JavaScript中怎么知道要执行的是哪一个回调函数呢?答案就是:任务被放入任务队列的时候,该任务的回调函数会被注册(注册到什么地方?须要进一步探究)。这样,当特定任务完成的时候,任务结果和回调标记会返回给JavaScript执行线程,进入执行栈。
与其余任务不一样,事件并非由JavaScript执行线程发出的,而是从UI线程中发出的。
事件处理器和回调函数相似。可是特定的事件处理器在浏览器进入异步事件驱动阶段时就会针对特定的事件注册。当事件对象返回到JavaScript执行线程时,事件处理器也会同时进入执行栈中执行。
越日后写,愈加现我以前的一些理解有误差。在学习过程当中,我也要多反思,多总结。以前写的不对的地方,我也会尽早纠正。