const PENDING = 'pending' // 等待
const FULFILLED = 'fulfilled' // 成功
const REJECTED = 'rejected' // 失败
class MyPromise {
constructor(exec) {
if (typeof exec !== 'function') {
throw new TypeError(`Promise resolver ${exec} is not a function`)
}
this.bindFunc()
this.initValue()
try {
exec(this.resolve, this.reject) // 立即执行的回调函数
} catch (error) {
this.reject(error)
}
}
resolve(value) {
// 如果状态是等待的话,就 允许改变状态
if (this.status === PENDING) {
this.status = FULFILLED
this.value = value
this.onFulfilledCallbacks.forEach(cb => {
cb(this.value)
})
}
}
reject(reason) {
if (this.status === PENDING) {
this.status = REJECTED
this.reason = reason
this.onRejectedCallbacks.forEach(cb => {
cb(this.reason)
})
}
}
bindFunc() {
this.resolve = this.resolve.bind(this)
this.reject = this.reject.bind(this)
}
initValue() {
this.status = PENDING // 初始化的值
this.value = undefined // 成功的值
this.reason = undefined // 失败的原因
this.onFulfilledCallbacks = [] // 成功回调
this.onRejectedCallbacks = [] // 失败回调
}
}
说实话,一开始有很好为什么这里的回调要使用数组
使用情况如下
const p = new Promise((resolve) => {resolve(1)})
p.then(() => {})
p.then(() => {})
p.then(() => {})
p.then(() => {})
class MyPromise {
...
then(onFulfilled, onRejected) {
// 可能有这种情况,也就是没有传 成功和失败函数
// .then().then().then((v) => {console.log(v)})
if (typeof onFulfilled !== 'function') {
onFulfilled = (value) => value
}
if (typeof onRejected !== 'function') {
onRejected = (reason) => { throw reason }
}
let promise2 = new MyPromise((resolve, reject) => {
if (this.status === FULFILLED) {
// 使用异步代码是为了 能够 在 resolvePromise 中 获取到 promise2
setTimeout(() => {
// 这里由于 前面使用了箭头函数,所以这里的 value 其实还是上一个 Promise 的 value
// 上一个 promise 的返回值,也就是下一个回调函数 传入的值
// 如果是普通值,直接调用 resole,这样就能实现链式调用 接下来的 then
// 如果 是 promise,查看 promise 对象返回的结果
// 再根据promise对象返回的结果,决定调用 resolve 还是 reject
try {
let x = onFulfilled(this.value)
MyPromise.resolvePromise(x, promise2, resolve, reject)
} catch (e) {
// 把错误传给接下来的 then
reject(e)
}
}, 0)
// resolve(x)
} else if (this.status === REJECTED) {
setTimeout(() => {
// 上一个 promise 的返回值,也就是下一个回调函数 传入的值
// 如果是普通纸,直接调用 resole,这样就能实现链式调用 接下来的 then
// 如果 是 promise,查看 promise 对象返回的结果
// 再更具promise对象返回的结果,决定调用 resolve 还是 reject
try {
let x = onRejected(this.reason)
MyPromise.resolvePromise(x, promise2, resolve, reject)
} catch (e) {
// 把错误传给接下来的 then
reject(e)
}
}, 0)
} else {
// 等待,将成功的回调和 失败的回调 存储起来
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
// 上一个 promise 的返回值,也就是下一个回调函数 传入的值
// 如果是普通纸,直接调用 resole,这样就能实现链式调用 接下来的 then
// 如果 是 promise,查看 promise 对象返回的结果
// 再更具promise对象返回的结果,决定调用 resolve 还是 reject
try {
let x = onFulfilled(this.value)
MyPromise.resolvePromise(x, promise2, resolve, reject)
} catch (e) {
// 把错误传给接下来的 then
reject(e)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
// 上一个 promise 的返回值,也就是下一个回调函数 传入的值
// 如果是普通纸,直接调用 resole,这样就能实现链式调用 接下来的 then
// 如果 是 promise,查看 promise 对象返回的结果
// 再更具promise对象返回的结果,决定调用 resolve 还是 reject
try {
let x = onRejected(this.reason)
MyPromise.resolvePromise(x, promise2, resolve, reject)
} catch (e) {
// 把错误传给接下来的 then
reject(e)
}
}, 0)
})
}
})
return promise2
}
// 统一解决 .then 的返回值
// 这里写的比较简单,但是主要功能已经体现
// 也就是当 返回值为 Promise 的时候
static resolvePromise(x, promise2, resolve, reject) {
if (x === promise2) {
return reject(new TypeError('不能循环调用promise'))
}
if (x instanceof MyPromise) {
// 就是 promise 对象
// 这样就能把当前的 执行返回结果 当做返回值,丢给接下来的 .then
// 相当于 把之前 .then 的执行权力 交给了 这个 x
x.then(resolve, reject)
} else {
resolve(x)
}
}
...
}
以上,promise的主体其实就完成了,接下来就是附带的那些函数了
class MyPromise {
...
catch(callback) {
return this.then(undefined, callback)
}
...
}
class MyPromise {
...
finally(callback) {
return this.then(
value => {
// 如果 callback 返回的是一个 promise ,那么就会直接返回 那个 promise
// 要注意的是,finally 是获取不到 promise 的 value 的
return new MyPromise.resolve(callback()).then(() => value)
}, reason => {
return new MyPromise.resolve(callback()).then(() => {throw reason})
})
}
...
}
class MyPromise {
...
// 如果传入进来的是 一个 promise ,那么 就直接使用这个 promise
static resolve (value) {
if (value instanceof MyPromise) {
return value
} else {
return new MyPromise(resolve => resolve(value))
}
}
...
}
class MyPromise {
...
static all(promises) {
let result = []
let length = 0
return new MyPromise((resolve, reject) => {
function addData(key, value) {
result[key] = value
length ++
// 等到所有值都获取完毕了,就可以结束了
if (length === promises.length) {
resolve(result)
}
}
for (let i = 0; i < promises.length; i++) {
const current = promises[i];
// 是 promise 对象的话,就执行 promise
if (current instanceof MyPromise) {
current.then((value) => {
addData(i, value)
}, reject)
} else {
// 普通值
addData(i, current)
}
}
})
}
...
}
class MyPromise {
...
static race(promises) {
return new MyPromise((resolve, reject) => {
// race 只需要返回第一个值就可以了
for (let i = 0; i < promises.length; i++) {
const current = promises[i];
// 是 promise 对象的话,就执行 promise
if (current instanceof MyPromise) {
current.then((value) => {
resolve(value)
}, reject)
} else {
// 普通值
resolve(current)
}
}
})
}
...
}
class MyPromise {
...
static allSettled(promises) {
let result = []
let length = 0
return new MyPromise((resolve, reject) => {
function addData(key, value, status) {
result[key] = {
[status === FULFILLED ? 'value' : 'reason']: value,
status
}
length ++
// 等到所有值都获取完毕了,就可以结束了
if (length === promises.length) {
resolve(result)
}
}
for (let i = 0; i < promises.length; i++) {
const current = promises[i];
// 是 promise 对象的话,就执行 promise
if (current instanceof MyPromise) {
// 无论是成功还是失败,都会将 返回值放到需要返回的数组中,集中返回
current.then(
(value) => { addData(i, value, FULFILLED) },
(reason) => { addData(i, reason, REJECTED) }
)
} else {
// 普通值
addData(i, current, FULFILLED)
}
}
})
}
...
}