Promise 源码分析与实现(学习笔记)
-
实现 Promise 代码的核心逻辑
1.Promise 就是一个类,在执行这个类的时候需要传递一个执行器进去,这个执行器会立即执行
-
Promise 中有三种状态,分别为 成功 fulfilled 失败 rejected 等待 pending
pending -> fulfilled
pending -> rejected -
resolve 和 reject 函数就是用来更改状态的
resolve: fulfilled
reject: rejected -
then 方法:
判断状态,若状态为成功,调用成功回调函数
如果状态为失败,调用失败回调函数
then 方法是被定义在原型对象中的 -
then 成功回调有一个参数,表示成功后的值
then 失败回调有一个参数,表示失败的原因 -
Promise 中加入异步调用 setTimeout 时,then 会比 setTimeout 先调用
此时调用 .then 方法时,还没有调用 resolve 和 reject 方法,状态为 pending
将成功回调和失败回调存储起来
异步调用执行完成后,调用 resolve 或 reject 时,调用之前存储的成功回调和失败回调 -
then 方法多次调用
每一个 then 方法中传递的回调函数都要被执行
每一个 then 方法中传递的回调函数都要被存储起来
异步调用执行完成后,调用 resolve 或 reject 时,依次调用之前存储回调函数 -
then 方法是可以被链式调用的,后面 then 方法的回调函数拿到的值是上一个 then 方法的回调函数的返回值
then 方法的链式调用 --> 返回 Promise 对象
拿到上一个 then 方法的回调函数的结果 -
如果 then 返回的是一个 Promise 对象,要判断状态,决定调用 resolve 还是 reject
-
then 方法链式调用识别 Promise 对象自返回
报出错误 Chaining cycle detected for promise # -
捕获错误
执行器当中的代码执行过程中发生错误时,状态变为错误状态
then 方法中的回调函数在执行过程中发生错误时,要在下一个 then 方法中报出错误 -
将 then 方法的参数变为可选参数
promise
.then() // .then(value => value)
.then()
.then(value => console.log(value)) -
Promise.all
静态方法,参数为一个数组 -
Promise.resolve 静态方法,返回一个 promise 对象,参数为普通值或 promise 对象
-
finally
无论当前 promise 对象最终是成功还是失败,都会被调用
后面可以用 then 方法,得到最终的值
定义在原型对象上
finally 方法的回调函数中可以 return 一个 promise 对象,此时应该等待这个 promise 对象执行完成之后,再执行下一个 then -
catch
定义在原型对象上
catch (failCallback) {
return this.then(undefined, failCallback)
}
实现代码:
const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
class MyPromise {
constructor (executor) {
// 执行器当中的代码执行过程中发生错误时,状态变为错误状态
try {
executor(this.resolve, this.reject)
} catch (e) {
this.reject(e)
}
}
// 状态定义成常量,为了复用和有提示
status = PENDING
// 成功之后的值
value = undefined
// 失败的原因
reason = undefined
// 成功回调
successCallback = []
// 失败回调
failCallback = []
resolve = value => {
// 如果状态不是等待,阻止程序向下执行
if (this.status !== PENDING) return
// 将状态改为成功
this.status = FULFILLED
// 保存成功之后的值
this.value = value
// 判断成功回调是否存在,如果存在,调用
while (this.successCallback.length) this.successCallback.shift()()
}
reject = reason => {
// 如果状态不是等待,阻止程序向下执行
if (this.status !== PENDING) return
// 将状态改为失败
this.status = REJECTED
// 保存失败的原因
this.reason = reason
// 判断失败回调是否存在,如果存在,调用
while (this.failCallback.length) this.failCallback.shift()()
}
then (successCallback, failCallback) {
// then 方法的链式调用 --> 返回 promise 对象
successCallback = successCallback ? successCallback : value => value
failCallback = failCallback ? failCallback : reason => { throw reason }
const promise2 = new Promise((resolve, reject) => {
// 判断状态
if (this.status === FULFILLED) {
setTimeout(() => {
try {
// 后面 then 方法的回调函数拿到的值是上一个 then 方法的回调函数的返回值
const x = successCallback(this.value)
// 判断 x 的值是普通值还是 promise 对象
// 如果是普通值,直接调用 resolve
// 如果是 promise 对象,查看 promise 对象返回的结果
// 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject
// 使用异步代码,获取到 promise2
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else if (this.status === REJECTED) {
setTimeout(() => {
try {
// 后面 then 方法的回调函数拿到的值是上一个 then 方法的回调函数的返回值
const x = failCallback(this.reason)
// 判断 x 的值是普通值还是 promise 对象
// 如果是普通值,直接调用 resolve
// 如果是 promise 对象,查看 promise 对象返回的结果
// 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject
// 使用异步代码,获取到 promise2
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
} else {
// 等待
// 将成功回调和失败回调存储起来
this.successCallback.push(() => {
setTimeout(() => {
try {
// 后面 then 方法的回调函数拿到的值是上一个 then 方法的回调函数的返回值
const x = successCallback(this.value)
// 判断 x 的值是普通值还是 promise 对象
// 如果是普通值,直接调用 resolve
// 如果是 promise 对象,查看 promise 对象返回的结果
// 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject
// 使用异步代码,获取到 promise2
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
this.failCallback.push(() => {
setTimeout(() => {
try {
// 后面 then 方法的回调函数拿到的值是上一个 then 方法的回调函数的返回值
const x = failCallback(this.reason)
// 判断 x 的值是普通值还是 promise 对象
// 如果是普通值,直接调用 resolve
// 如果是 promise 对象,查看 promise 对象返回的结果
// 再根据 promise 对象返回的结果,决定调用 resolve 还是 reject
// 使用异步代码,获取到 promise2
resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
}, 0)
})
}
})
return promise2
}
finally (callback) {
// 无论当前 promise 对象最终是成功还是失败,都会被调用
// 后面可以用 then 方法,得到最终的值
// finally 方法的回调函数中可以 return 一个 promise 对象,此时应该等待这个 promise 对象执行完成之后,再执行下一个 then
return this.then(value => {
return MyPromise.resolve(callback()).then(() => value)
}, reason => {
return MyPromise.resolve(callback()).then(() => {throw reason})
})
}
catch (failCallback) {
return this.then(undefined, failCallback)
}
static all (array) {
const result = []
let index = 0
return new Promise((resolve, reject) => {
const addData = (key, value) => {
result[key] = value
index++
if (index === array.length) {
resolve(result)
}
}
for (let i = 0; i < array.length; i++) {
let current = array[i]
if (current instanceof MyPromise) {
// promise 对象
current.then(value => addData(i, value), reason => reject(reason))
} else {
// 普通值
}
}
resolve()
})
}
static resolve (value) {
// 判断参数是否为一个 promise
// 如果是,直接返回这个 promise 对象
// 如果不是,把值包裹起来,返回一个 promise 对象
if (value instanceof MyPromise) return value
return new MyPromise(resolve => resolve(value))
}
}
const resolvePromise = (promise2, x, resolve, reject) => {
if (promise2 === x) {
// 自己返回自己
return reject(new TypeError('Chaining cycle detected for promise #<Promise>'))
}
if (x instanceof MyPromise) {
// promise 对象
// x.then(value => resolve(value), reason => reject(reason))
x.then(resolve, reject)
} else {
// 普通值
resolve(x)
}
}
module.exports = MyPromise