JS的运行环境是一个很复杂的环境,它里面有非常多的复杂的名词事物,用简单又不严谨的说法来说,运行环境里至少有下面这些事物:
1. 事件队列 (Event Queue):
* 它是一个即将被执行的任务的列表,它负责给任务排序。
* 事件队列不止一个,是有多个
(比如输入事件有一个自己的队列,定时器有一个自己的队列,所有回调函数也有一个自己的队列)
(队列有优先级,比如输入事件优先级注定高,因为从用户感受来说,用户的输入如果优先级不高,用户会觉得浏览器响应慢; 另有一些队列优先级低,比如回调函数队列)
最终,这些队列会形成一个总队列,而且,这个总队列随时会变化,因为优先级的关系,经常会有插队的事情发生.
例如: +++++++~~~=======########, 代表总队列,分为若干个子队列,每一个子队列如果有新任务,也只会加到自己的队列的末尾,而不会加到总队列的末尾。有一个执行器会挨个执行总队列里的任务。
//////////////////////////////////////////////////////////
2. 栈 (stack):它负责根据事件队列来执行任务,就是说,进来一个任务,然后执行,然后扔出去。栈相当于流水线上的干活的操作臂。
//////////////////////////////////////////////////////////
3. 事件循环 (Event Loop):事件循环是事件队列和栈的关联的桥梁,它做的事情是:如果栈空了,事件队列还没空,那么事件循环就从事件队列拿出来一个任务,扔给栈。事件循环相当于一个有眼睛的机械臂,它看到栈空了,事件队列还有任务,就把任务的第一个抓出来扔给栈,它自己就完事了。
/////////////////////////////////////////////////////////
4.主线程:JS是单线程, 其他线程包括HTTP线程、I/O线程、GUI线程等等,这些线程由浏览器提供,跟JS的线程是两回事了。JS的线程称为主线程。
///////////////////////////////////////////////////////////
[异步任务的执行机制]
当主线程遇到一个异步任务,是立即执行的,并不会像想象的,拖到所有同步任务的最后面.
任务的回调会插入到回调函数队列中,因为回调函数队列的优先级很低,所以会排到总队列的最后面,其结果就是:主线程把同步任务都完成了,才开始执行异步事件的回调。
注意,并不是异步任务在全体同步任务结束之后才开始,而是异步任务的回调通常在全体同步任务结束之后才开始!
///////////////////////////////////////////////////////////////////////////
转载自: microkof的简书