Promise实现
const PENDING = 'pending'
const FULFILLED = 'fulfilled'
const REJECTED = 'rejected'
class MPromise {
FULFILLED_CALLBACK_LIST = []
REJECTED_CALLBACK_LIST = []
// 私有变量,存储真正的status
_status = PENDING
constructor(fn) {
this.status = PENDING
// fulfilled 值
this.value = null
// rejected 值
this.reason = null
try {
fn(this.resolve.bind(this), this.reject.bind(this))
} catch (e) {
this.reject(e)
}
}
get status() {
return this._status
}
set status(newStatus) {
this._status = newStatus
switch (newStatus) {
case FULFILLED: {
this.FULFILLED_CALLBACK_LIST.forEach(callback => {
callback(this.value)
});
break
}
case REJECTED: {
this.REJECTED_CALLBACK_LIST.forEach(callback => {
callback(this.reason)
});
break
}
}
}
resolve(value) {
if (this.status === PENDING) {
this.value = value
this.status = FULFILLED
}
}
reject(reason) {
if (this.status === PENDING) {
this.reason = reason
this.status = REJECTED
}
}
// param:Promise 结束后调用的 Function。
// return: 一个设置了 finally 回调函数的 Promise 对象。这个Promise对象可以继续finally之前then的结果
finally(callback) {
return this.then(value => {
return MPromise.resolve(callback()).then(() => value)
}, err => {
return MPromise.resolve(callback()).then(() => { throw err })
})
}
then(onFulfilled, onRejected) {
const realOnFulfilled = this.isFunction(onFulfilled) ? onFulfilled : value => value
const realOnRejected = this.isFunction(onRejected) ? onRejected : reason => { throw reason }
const promise2 = new MPromise((resolve, reject) => {
const fulfilledMicrotask = () => {
queueMicrotask(() => {
try {
// 实现链式调用的关键
const x = realOnFulfilled(this.value)
this.resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
const rejectedMicrotask = () => {
queueMicrotask(() => {
try {
// 实现链式调用的关键
const x = realOnRejected(this.reason)
this.resolvePromise(promise2, x, resolve, reject)
} catch (e) {
reject(e)
}
})
}
switch (this.status) {
case FULFILLED: {
fulfilledMicrotask()
break
}
case REJECTED: {
rejectedMicrotask()
break
}
case PENDING: {
this.FULFILLED_CALLBACK_LIST.push(fulfilledMicrotask)
this.REJECTED_CALLBACK_LIST.push(rejectedMicrotask)
}
}
})
return promise2
}
resolvePromise(promise2, x, resolve, reject) {
// 简单版本: resolve(x)
// 以下为复杂版本:
if (promise2 === x) {
return reject(new TypeError('param and return are same'))
}
if (x instanceof MPromise) {
queueMicrotask(() => {
x.then(y => {
this.resolvePromise(promise2, y, resolve, reject)
}, reject)
})
} else if (x && (typeof x === 'object' || this.isFunction(x))) {
let then = null
try {
then = x.then
} catch (e) {
return reject(e)
}
// 如果then是函数
if (this.isFunction(then)) {
let called = false
try {
then.call(x, y => {
if (called) return
called = true
this.resolvePromise(promise2, y, resolve, reject)
}, r => {
if (called) return
called = true
reject(r)
})
} catch (e) {
if (called) {
return
}
reject(e)
}
} else {
resolve(x)
}
} else {
resolve(x)
}
}
catch(onRejected) {
return this.then(null, onRejected)
}
isFunction(param) {
return typeof param === 'function'
}
// Promise.resolve() 静态方法将给定的值转换为一个 Promise。如果该值本身就是一个 Promise,那么该 Promise 将被返回;
static resolve(value) {
if (value instanceof MPromise) {
return value
}
return new MPromise(resolve => resolve(value))
}
// Promise.reject() 静态方法返回一个已拒绝(rejected)的 Promise 对象,拒绝原因为给定的参数。
static reject(reason) {
return new MPromise((resolve, reject) => {
reject(reason)
})
}
// Promise.race(promiseList) 返回一个 Promise。这个返回的 promise 会随着第一个 promise 的敲定而敲定。
static race(promiseList) {
return new MPromise((resolve, reject) => {
const length = promiseList.length
if (length === 0) {
return resolve()
} else {
for (let i = 0; i < length; i++) {
MPromise.resolve(promiseList[i])
.then(v => resolve(v))
.catch(r => reject(r))
}
}
})
}
// Promise.all(promiseList) 返回一个 Promise。当所有输入的 Promise 都被兑现时,返回的 Promise 也将被兑现(即使传入的是一个空的可迭代对象),并返回一个包含所有兑现值的数组。如果输入的任何 Promise 被拒绝,则返回的 Promise 将被拒绝,并带有第一个被拒绝的原因。
static all(promiseList) {
return new MPromise((resolve, reject) => {
const length = promiseList.length
if (length === 0) {
return MPromise.resolve([])
}
let count = 0,
result = new Array(length)
for (let i = 0; i < length; j++) {
MPromise.resolve(promiseList[i])
.then((val) => {
count++;
result[i] = val
if (count === length) {
return resolve(result)
}
})
.catch(r => reject(r))
}
})
}
// Promise.any(promiseList) 返回一个 Promise。当输入的任何一个 Promise 兑现时,这个返回的 Promise 将会兑现,并返回第一个兑现的值。当所有输入 Promise 都被拒绝(包括传递了空的可迭代对象)时,它会以一个包含拒绝原因数组的 AggregateError 拒绝。
static any(promiseList) {
return new MPromise((resolve, reject) => {
const length = promiseList.len
if (length === 0) {
return MPromise.resolve([])
}
let errcount = 0
const errResult = new Array(length)
for (let i = 0; i < length; i++) {
MPromise.resolve(promiseList[i])
.then(v => resolve(v))
.catch(r => {
errResult[i] = reject(i)
errcount++
if (errcount.length === length) {
reject(errResult)
}
})
}
})
}
// Promise.allSettled(promiseList) 返回一个单独的 Promise。当所有输入的 Promise 都已敲定时(包括传入空的可迭代对象时),返回的 Promise 将被兑现,并带有描述每个 Promise 结果的对象数组。
// PromiseState 一直为 fulfilled
static allSettled(promiseList) {
return MPromise((resolve) => {
const length = promiseList.len
if (length === 0) {
return MPromise.resolve([])
}
const resultArr = new Array[length]
let count = 0
for (let i = 0; i < length; i++) {
MPromise.resolve(promiseList[i])
.then(value => {
resultArr[i] = {
value,
status: FULFILLED
}
count++
if (count === length) {
resolve(resultArr)
}
})
.catch(reason => {
resultArr[i] = {
reason,
status: REJECTED
}
count++
if (count === length) {
resolve(resultArr)
}
})
}
})
}
}
module.exports = MPromise
const test = new MPromise((resolve, reject) => {
setTimeout(() => {
resolve(111)
// reject(1)
}, 1000)
}).then(v => console.log(`[then] value=${v}`)).catch(r => console.log(`[catch] reason = ${r}`))
// console.log(test)