线程、事件循环、任务队列
JavaScript 是单线程的,但是却能执行异步任务,这主要是因为 JS 中存在事件循环(Event Loop)和 任务队列(Task Queue)。
**主线程:**JS只有一个线程,称之为主线程。而事件循环是主线程中执行栈里的代码执行完毕之后,才开始执行的。所以,主线程中要执行的代码时间过长,会阻塞事件循环的执行,也就会阻塞异步操作的执行。只有当主线程中执行栈为空的时候(即同步代码执行完后),才会进行事件循环来观察要执行的事件回调,当事件循环检测到任务队列中有事件就取出相关回调放入执行栈中由主线程执行。
事件循环: 由于主线程不断的重复获得任务、执行任务、再获取任务、再执行,所以这种机制被称为事件循环(event loop)。
**任务队列(消息队列):**异步操作会将相关回调添加到任务队列中。而不同的异步操作添加到任务队列的时机也不同,如 onclick,setTimeout,ajax处理的方式都不同。这些异步操作是由浏览器内核的webcore来执行的,webcore 包含3中webAPI,分别是 DOM Binding、network、timer 模块。
DOM Binding 模块处理一些DOM绑定事件,如 onclick 事件当事件触发的时候,回调函数会立即被webcore添加到任务队列中。
timer 模块会对 setTimeout 等计时器进行延时处理,当时间到达的时候,才会将回调函数添加到任务队列中。
network 模块处理 Ajax请求,在网络请求完成返回之后,才会将对应的回调添加到任务队列中。
JS在处理任务的时候,可以分为同步任务和异步任务。只有当同步任务都执行完毕之后,才会到任务队列里面执行异步任务。
在任务队列中,也分为宏任务和微任务,分别在宏任务队列和微任务队列,只有微任务队列中的任务全部执行完毕后,才会执行宏任务队列里面的任务。