JS是单线程语言,但倘若只有同步模式,遇到耗时操作,页面便会阻塞,就像接口请求不到数据,或者图片未加载完成,页面就卡住一直等待。这样显然不现实也不实用。所以异步模式应运而生。
EventLoop
JS的任务可以分为同步任务和异步任务
运行时,遇到同步任务,会根据执行顺序将同步任务加入执行栈中运行
遇到异步任务,会将异步任务移入事件注册表(event Table)注册函数
注册完成后将回调函数放入事件队列中(event Queue)
同步任务执行完毕后,会依次将事件队列中回调函数加入执行栈运行
宏任务和微任务
异步任务可以分为宏任务和微任务
他们的回调函数存放的地方叫宏任务队列、微任务队列
同步任务执行完成后,依次从微任务队列获取事件加入执行栈执行
微任务队列执行完成后,再执行宏任务队列
每次宏任务执行完毕后,都需要判断微任务队列是否为空
不为空优先执行微任务队列,直到微任务执行完毕
再继续执行宏任务
宏任务:script(主线程)、setTimeout、setInterval、setImmediate
微任务:Promise的then(promise传入的执行函数会立即执行属于同步)、process.nextTick(node环境)、Object.observe(已废弃)、 MutationObserver(观测dom变化)、queueMicrotask(将普通函数插入微任务队列中)
new Promise属于同步任务
为什么要分微任务和宏任务?
微任务是线程之间的切换,速度快。不用进行上下文切换,可以快速的一次性做完所有的微任务。
宏任务是进程之间的切换,速度慢,且每次执行需要切换上下文。因此一个Eventloop中只执行一个宏任务。
而区分微任务和宏任务的根本原因是为了插队。由于微任务执行快,一次性可以执行很多个,在当前宏任务执行后立刻清空微任务可以达到伪同步的效果,这对视图渲染效果起到至关重要的作用。