要让不同类型的任务在主线程中有条不紊地执行,这就需要有一个事件循环系统,用来负责接收、调度这些不同的事件。
浏览器运行时负责给引擎线程发送消息,只负责生产消息,不负责取消息。(发送什么消息,发到哪里)
我们所熟悉的引擎是chrome浏览器中和node.js中使用的V8引擎。
这个引擎主要由两个部分组成,内存堆和调用栈。(只负责取消息,不负责生产消息)
主线程:顺序执行,(遇到异步任务,注册函数,通过event loop线程通知相应的工作线程(如ajax,dom,setTimout等)),继续执行后面
等到工作线程完成了任务,eventloop线程会将消息添加到消息队列中
线程上调用栈为空就执行消息队列中排在最前面的消息,依次执行
事件循环:就是主线程重复从消息队列中取消息、执行的过程
但是在ES6引入了promise后,产生了一个新的名词”微任务(microtask)“。微任务的执行顺序与之前我们所说的任务(我们可以称之为”宏任务“)
- 一个线程中,事件循环是唯一的,但是任务队列可以拥有多个。
- 任务队列又分为macro-task(宏任务)与micro-task(微任务),在最新标准中,它们被分别称为task与jobs。
-
事件循环的顺序,决定了JavaScript代码的执行顺序。它从script(整体代码)开始第一次循环。之后全局上下文进入函数调用栈。直到调用栈清空(只剩全局),然后执行所有的micro-task。当所有可执行的micro-task执行完毕之后。循环再次从macro-task开始,找到其中一个任务队列执行完毕,然后再执行所有的micro-task,这样一直循环下去。
- 其中每一个任务的执行,无论是macro-task还是micro-task,都是借助函数调用栈来完成
在某一个宏任务执行完后,在重新渲染与开始下一个宏任务之前,就会将在它执行期间产生的所有微任务都执行完毕(在渲染前)