简介
Javascript是单线程的。而在主线程之外,为了协调事件、用户交互、脚本、渲染、网络等,用户代理(user agents,一般指浏览器)必须使用一种机制来保证程序的正确运行。这种机制就是事件循环(event loops)。当主线程(栈)执行完毕后,就开始事件循环。事件循环有两种形式,分别是browsing contexts、workers(Web Worker)
Browsing contexts是一个浏览器展示Document的环境(一般来说是一个浏览器标签页,但也有可能是一个页面内的window或者frame)。
Web Works是H5的一个API,用来开辟一个新的线程。在Worker内部不能访问主程序的任何资源。与主程序的交互通过postMessage
和message
事件。但是Worker内部仍可以执行网络操作(Ajax、WebSocket)以及定时器等。所以这里也有独立的事件循环。
关键点
有几个概念需要知道。
- 一个事件循环有一个或者多个task queues。
- 事件循环中的每一个task和Document相关联。如果这个任务在一个元素的上下文排队,那么这个任务是该元素的node document。
- 每一个任务来自于某个特定的任务源(task source)。
- DOM操作事件源(添加删除dom元素)
- 用户交互事件源
- 网络事件源(响应网络活动)
- history事件源(history.back()等)
- 当用户代理添加一个任务的时候,根据任务源不同,会被添加到不同的task queues。
- 每个task queues保证任务是先进先出的。
- 对于不同的task queues,用户代理可能分配的时间不同。比如对于鼠标和键盘事件所在的task queues,用户代理可能分配3/4的时间,同时也不会让其他的task queues得不到执行。
- 每一个事件循环有一个currently running task(当前运行的任务)。开始,它是null。每当执行一个任务的时候,currently running task即这个正在执行的任务。执行完成后,被重置为null。
Jobs and Job Queues and promise
在讲macro-task和micro-task之前,这部分内容起到承上启下的作用。该部分内容在es6(ecma-262)规范。
Job只能在没有running execution context和execution