Promise 中的执行函数是同步进行的,但是里面存在着异步操作,在异步操作结束后会调用 resolve 方法,或者中途遇到错误调用 reject 方法,这两者都是作为微任务进入到 EventLoop 中。但是你有没有想过,Promise 为什么要引入微任务的方式来进行回调操作?
解决方式
回到问题本身,其实就是如何处理回调的问题。总结起来有三种方式:
- 使用同步回调,直到异步任务进行完,再进行后面的任务。
- 使用异步回调,将回调函数放在进行
宏任务队列
的队尾。 - 使用异步回调,将回调函数放到
当前宏任务中
的最后面。
优劣对比
第一种方式显然不可取,因为同步的问题非常明显,会让整个脚本阻塞住,当前任务等待,后面的任务都无法得到执行,而这部分等待的时间
是可以拿来完成其他事情的,导致 CPU 的利用率非常低,而且还有另外一个致命的问题,就是无法实现延迟绑定
的效果。
如果采用第二种方式,那么执行回调(resolve/reject)的时机应该是在前面所有的宏任务
完成之后,倘若现在的任务队列非常长,那么回调迟迟得不到执行,造成应用卡顿
。
为了解决上述方案的问题,另外也考虑到延迟绑定
的需求,Promise 采取第三种方式, 即引入微任务
, 即把 resolve(reject) 回调的执行放在当前宏任务的末尾。
这样,利用微任务
解决了两大痛点:
- 采用异步回调替代同步回调解决了浪费 CPU 性能的问题。
- 放到当前宏任务最后执行,解决了回调执行的实时性问题。