Promise 是一种 JavaScript 异步编程的解决方案,它可以避免回调函数嵌套和代码可读性差的问题。Promise 是一个表示异步操作的对象,它有三种状态:Pending(等待态)、Resolved(成功态)、Rejected(失败态)。
Promise 的原理可以分为以下几个部分:
- Promise 对象的状态可以从 Pending 转变为 Resolved 或 Rejected,但一旦状态发生变化就无法再次改变。
- Promise 对象有一个 then 方法,可以注册 Resolved 或 Rejected 状态变化后的回调函数,它返回的是一个新的 Promise 对象。
- then 方法接受两个回调函数作为参数,第一个函数用于处理 Resolved 状态,第二个函数用于处理 Rejected 状态。
- 如果 then 方法的回调函数返回一个 Promise 对象,那么 then 方法返回的新 Promise 对象会等待该 Promise 对象的状态变化,然后根据该 Promise 对象的状态再次改变自身状态。
- 如果 then 方法的回调函数返回一个非 Promise 对象的值,那么 then 方法返回的新 Promise 对象状态为 Resolved,值为该非 Promise 对象的值。
- 如果 then 方法的回调函数抛出一个异常,那么 then 方法返回的新 Promise 对象状态为 Rejected,值为该异常。
Promise 的实现依赖于 JavaScript 的事件循环机制,它使用微任务(microtask)和宏任务(macrotask)来管理异步操作的执行顺序。当 Promise 对象的状态变化时,它会根据 Promise 对象的状态和注册的回调函数类型(Resolved 或 Rejected)将回调函数放入微任务队列或宏任务队列中,等待事件循环机制调度执行。
下面是代码实现过程
使用ts能够更好的对类进行标记与规范,这里使用了泛型类来实现的。
export default class CustomPromise<T> {
private status: "pending" | "fulfilled" | "rejected" = "pending";
private results: T | undefined;
private error: any;
private resolveCbs: ((results: T) => void)[] = [];
private rejectCbs: ((error: any) => void)[] = [];
constructor (executor: (resolve: (results: T) => void, reject: (error: any) => void) => void) {
executor(this.resolve.bind(this), this.reject.bind(this))
}
// pending => fulfilled
private resolve (results: T) {
if (this.status === "pending") {
this.status = "fulfilled"
this.results = results
this.resolveCbs.forEach(cb => cb(results))
}
}
// pending => rejected
private reject (error: any) {
// console.log("reject:外", error);
// console.log(this.rejectCbs);
if (this.status === "pending") {
this.status = "rejected"
this.error = error
this.rejectCbs.forEach(cb => cb(error))
}
}
// 执行then 回调
public then (onSuccessFn?: (results: T | undefined) => void, onErrorFn?: (error: any) => void) {
// 链式调用 => return Promise
// 如果 then 方法的回调函数返回一个 Promise 对象,那么 then 方法返回的新 Promise 对象会等待该 Promise 对象的状态变化,然后根据该 Promise 对象的状态再次改变自身状态。
// 如果 then 方法的回调函数返回一个非 Promise 对象的值,那么 then 方法返回的新 Promise 对象状态为 Resolved,值为该非 Promise 对象的值。
// 如果 then 方法的回调函数抛出一个异常,那么 then 方法返回的新 Promise 对象状态为 Rejected,值为该异常。
const promise = new CustomPromise((resolve, reject) => {
if (this.status === "fulfilled") {
// 这里的 try catch 是为了验证.then函数是否能正常执行,以下同
try {
const results = onSuccessFn ? onSuccessFn(this.results) : undefined
resolve(results)
} catch (error) {
reject(error)
}
}
else if (this.status === "rejected") {
try {
const results = onErrorFn ? onErrorFn(this.error) : undefined;
resolve(results)
} catch (error) {
reject(error)
}
}
else {
this.resolveCbs.push((results) => {
try {
const newResults = onSuccessFn ? onSuccessFn(results) : undefined
resolve(newResults)
} catch (error) {
reject(error)
}
})
this.rejectCbs.push((error) => {
console.log(error);
try {
const newResult = onErrorFn ? onErrorFn(error) : undefined;
resolve(newResult)
} catch (error) {
reject(error)
}
})
}
})
return promise
}
// 执行catch 回调
public catch (onErrorFn?: (results: any) => void) {
return this.then(undefined, onErrorFn)
}
}
重点:
1、要对then函数深度解读
2、JavaScript 的事件循环机