Promise源码解析
关键点记录
如何通过then()实现将异步结果返回?原理:
通过三种状态判断异步操作是否已经执行成功1
2
3const PENDING = 'pending'; //初始状态
const FULFILLED = 'fulfilled'; // 成功状态
const REJECTED = 'rejected'; // 失败状态通过成功回调的数组onResolveCallbacks,以及失败回调的数组onRejectedCallbacks
存放then()方法接收的回调函数执行then()方法之后,如果状态是 pending,则存入回调数组中
在异步执行完成后,会调用 resolve 以及 reject
此时,会相应改变状态以及调用回调数组中的回调方法,达到在异步操作完成后执行回调的结果then() 会返回 promise 对象
then()方法需要生成微任务
ES6中的promise实现
微任务的生成是按照执行环境的不同而使用不同的生成方式
附上生成部分的源码:
1
2
3
4
5
6
7
8
9
10
11
12
13let scheduleFlush
// Decide what async method to use to triggering processing of queued callbacks:
if (isNode) { // node环境 使用 process.nextTick()
scheduleFlush = useNextTick()
} else if (BrowserMutationObserver) {
scheduleFlush = useMutationObserver() // 浏览器环境 使用MutaionObserver()
} else if (isWorker) {
scheduleFlush = useMessageChannel()
} else if (browserWindow === undefined && typeof require === 'function') {
scheduleFlush = attemptVertx()
} else {
scheduleFlush = useSetTimeout() // 无法判断环境 使用 setTimeout()
}promise链式调用
promise.then()返回一个promise对象在then()方法里面,return promise2 = new Promise((resolve, reject) => {})
会先调用promise1的then()方法传入的回调函数 调用完成后,将调用结果 x 作为promise2的值 resolve(x)
promise.all()
返回一个promise,resolve 一个结果数组接收一个数组参数
对数组每一项进行判断并处理
若是普通值,则直接存放在 result 中
若是promise,则调用 then() 方法,将结果存放到result并且,result 的顺序严格按照传入参数数组的顺序
(在对参数数组进行遍历操作时,会把下标传递给结果处理函数,存放到 result 的对应位置)1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27// 封装 Promise.all方法
Promise.all = function (values) {
return new Promise((resolve, reject) => {
let result = [] // 存放返回值
let counter = 0 // 计数器,用于判断异步完成
function processData(key, value) {
result[key] = value
// 每成功一次计数器就会加1,直到所有都成功的时候会与values长度一致,则认定为都成功了,所以能避免异步问题
if (++counter === values.length) {
resolve(result)
}
}
// 遍历 数组中的每一项,判断传入的是否是promise
for (let i = 0; i < values.length; i++) {
let current = values[i]
// 如果是promise则调用获取data值,然后再处理data
if (isPromise(current)) {
current.then(data => {
processData(i, data)
}, reject)
} else {
// 如果不是promise,传入的是普通值,则直接返回
processData(i, current)
}
}
})
}
promise简单总结记忆
链式调用需要等待上一个 then() 的微任务完成才会进行注册
若有上一个 then() return 则下一个 then() 需要等 return的内容执行完成才进行注册
参考:
https://github.com/xieranmaya/blog/issues/3
检测(是否理解):
https://blog.csdn.net/lqyygyss/article/details/102662606
Promise/A+ 规范(中文版):
https://www.icode9.com/content-4-365156.html