👋 最近重新学习了Promise对象,有了很多新的感悟
面试中我们也经常会遇到类似的题目,手写实现 Promise.xxx 诸如此类
今天主题是尝试手写实现一下大致的Promise,当作学习总结和回顾
constructor
实例化一个 Promise 对象时,我们会这么用
const promise = new Promise((resolve, reject) => {})
说明这个构造函数接收一个函数,这个函数可以拿到 resolve 和 reject 这两个方法
promise符合 PromiseA+ 规范,维护自身的状态
class MyPromise {
constructor(fn) {
this.state = "pendding"
this.value = null
this.reason = null
this.onFulfilledCallbacks = []
this.onRejectedCallbacks = []
const resolve = (value) => {
if (this.state === "pendding") {
this.state = "fulfilled"
this.value = value
this.onFulfilledCallbacks.forEach((callback) => {
callback(value)
})
}
}
const reject = (reason) => {
if (this.state === "pendding") {
this.state = "rejected"
this.reason = reason
this.onRejectedCallbacks.forEach((callback) => {
callback(reason)
})
}
}
try {
fn(resolve, reject)
} catch (error) {
reject(error)
}
}
}
then
.then 方法返回一个新的 Promise,因此我们可以链式调用
该方法还有两个参数,状态变更为 fulfilled时候的回调函数和为 rejected 时候的回调函数
then(onFulfilled, onRejected) {
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : (value) => value
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason
}
const promise2 = new MyPromise((resolve, reject) => {
if (this.state === "onFulfilled") {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.state === "onRejected") {
setTimeout(() => {
try {
const x = onRejected(this.reason)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
} else if (this.state === "pendding") {
this.onFulfilledCallbacks.push(() => {
setTimeout(() => {
try {
const x = onFulfilled(this.value)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
this.onRejectedCallbacks.push(() => {
setTimeout(() => {
try {
const x = onRejected(this.reason)
this.resolvePromise(promise2, x, resolve, reject)
} catch (error) {
reject(error)
}
}, 0)
})
}
})
return promise2
}
resolvePromise
在 .then 方法中,有一个 resolvePromise 用来处理回调函数返回的结果
resolvePromise(promise2, x, resolve, reject) {
if (promise2 === x) {
return reject(new TypeError("Chaining cycle detected for promise"))
}
let called = false
if (x instanceof MyPromise) {
x.then(
(y) => {
if (called) return
called = true
this.resolvePromise(promise2, y, resolve, reject)
},
(reason) => {
if (called) return
called = true
reject(reason)
}
)
} else if (x && (typeof x === "object" || typeof x === "function")) {
try {
const then = x.then
if (typeof then === "function") {
then.call(
x,
(y) => {
if (called) return
called = true
this.resolvePromise(promise2, y, resolve, reject)
},
(reason) => {
if (called) return
called = true
reject(reason)
}
)
} else {
resolve(x)
}
} catch (error) {
if (called) return
called = true
reject(error)
}
} else {
resolve(x)
}
}
catch
.catch 方法其实就是 .then 方法只传递第二个参数
catch(onRejected) {
return this.then(null, onRejected)
}
finally
.finally 方法无论 Promise 结果如何,都会触发
finally(fn) {
return this.then(
(value) => {
return MyPromise.resolve(fn()).then(() => value)
},
(reason) => {
return MyPromise.resolve(fn()).then(() => {
throw reason
})
}
)
}
resolve
Promise.resolve 是 Promise 对象的静态方法,将传入的参数转换成 Promise 对象返回
static resolve(value) {
if (value instanceof MyPromise) return value
return new MyPromise((resolve) => resolve(value))
}
reject
Promise.reject 是 Promise 对象的静态方法,将传入的参数当作 reject 的理由抛出
static reject(reason) {
return new MyPromise((_, reject) => reject(reason))
}
all
Promise.all 接收一个 promise 数组,所有结果都为 fulfilled 时会返回所有的结果
static all(promises) {
return new MyPromise((resolve, reject) => {
if (!Array.isArray(promises)) {
return reject(TypeError("Arguments must be Array"))
}
let promisesCounter = 0
let promisesNum = promises.length
const resolvedRes = []
for (let i = 0; i < promisesNum; i++) {
MyPromise.resolve(promises[i]).then((value) => {
promisesCounter++
resolvedRes.push(value)
if (promisesCounter === promisesNum) {
return resolve(resolvedRes)
}
}, reject)
}
})
}
allSettled
Promise.allSettled 方法接收一个 promise 数组,不论结果如何都会返回最终结果
static allSettled(promises) {
return new MyPromise((resolve) => {
if (!Array.isArray(promises)) return resolve([])
let promisesNum = promises.length
let promisesCounter = 0
const res = []
for (let i = 0; i < promisesNum; i++) {
MyPromise.resolve(promises[i]).then(
(value) => {
promisesCounter++
res.push({ state: "fulfilled", value })
if (promisesCounter === promisesNum) {
return resolve(res)
}
},
(reason) => {
promisesCounter++
res.push({ state: "rejected", reason })
if (promisesCounter === promisesNum) {
return resolve(res)
}
}
)
}
})
}
race
Promise.race 方法接收一个 promise 数组,返回最先处理完成的结果,无论是什么状态
static race(promises) {
return new MyPromise((resolve, reject) => {
if (!Array.isArray(promises)) return reject(TypeError("Argument must be Array"))
for (let i = 0; i < promises.length; i++) {
MyPromise.resolve(promises[i]).then(resolve, reject)
}
})
}
any
Promise.any 方法接收一个 promise 数组,只要任何一个 promise 状态为 fulfilled,就返回他,如果所有的状态都为 rejected,则抛出一个错误
static any(promises) {
return new MyPromise((resolve, reject) => {
if (!Array.isArray(promises)) return reject(TypeError("Argument must be Array"))
let rejectedCounter = 0
let promisesNum = promises.length
let rejectedRes = []
for (let i = 0; i < promisesNum; i++) {
MyPromise.resolve(promises[i]).then(resolve, (reason) => {
rejectedRes.push(reason)
rejectedCounter++
if (rejectedCounter === promisesNum) {
// all promises rejected
return reject(new AggregateError(rejectedRes))
}
})
}
})
}
🎉 结束,如有问题欢迎留言,指正。