返回
PromiseA+规范 - 手写Promise的艺术
前端
2023-09-30 13:55:46
PromiseA+规范的深入理解
PromiseA+规范是JavaScript中异步编程的标准规范,它定义了Promise对象的行为和用法。Promise对象可以用来表示一个异步操作的结果,它提供了一个统一的接口来处理异步任务。
Promise对象有三个状态:pending(等待)、fulfilled(完成)和rejected(拒绝)。当一个Promise对象被创建时,它处于pending状态。当异步操作完成时,Promise对象的状态变为fulfilled或rejected,这取决于异步操作是否成功。
Promise的本质 - then方法
Promise对象最重要的特性就是它的then方法。then方法允许我们注册回调函数,以便在Promise对象的状态改变时执行相应的操作。then方法接受两个参数:
- onFulfilled:当Promise对象的状态变为fulfilled时执行的回调函数。
- onRejected:当Promise对象的状态变为rejected时执行的回调函数。
手写Promise的then方法
为了更好地理解Promise的本质,我们现在来一步步手写Promise的then方法。首先,我们需要定义一个Promise类:
class Promise {
constructor(executor) {
this.state = 'pending';
this.value = null;
this.reason = null;
this.onFulfilledCallbacks = [];
this.onRejectedCallbacks = [];
// 立即执行executor函数
executor(resolve, reject);
}
then(onFulfilled, onRejected) {
// 处理onFulfilled参数
if (typeof onFulfilled !== 'function') {
onFulfilled = function(value) {
return value;
};
}
// 处理onRejected参数
if (typeof onRejected !== 'function') {
onRejected = function(reason) {
throw reason;
};
}
// 创建一个新的Promise对象
const newPromise = new Promise((resolve, reject) => {
// 如果当前Promise对象的状态是pending,则将回调函数存储起来
if (this.state === 'pending') {
this.onFulfilledCallbacks.push(() => {
// 使用try-catch块来捕获onFulfilled函数可能抛出的错误
try {
// 执行onFulfilled函数
const value = onFulfilled(this.value);
// 根据onFulfilled函数的返回值来解析新Promise对象的状态
resolvePromise(newPromise, value);
} catch (err) {
// 如果onFulfilled函数抛出错误,则将新Promise对象的状态置为rejected
reject(err);
}
});
this.onRejectedCallbacks.push(() => {
// 使用try-catch块来捕获onRejected函数可能抛出的错误
try {
// 执行onRejected函数
const reason = onRejected(this.reason);
// 根据onRejected函数的返回值来解析新Promise对象的状态
resolvePromise(newPromise, reason);
} catch (err) {
// 如果onRejected函数抛出错误,则将新Promise对象的状态置为rejected
reject(err);
}
});
}
// 如果当前Promise对象的状态不是pending,则立即执行回调函数
else if (this.state === 'fulfilled') {
// 使用try-catch块来捕获onFulfilled函数可能抛出的错误
try {
// 执行onFulfilled函数
const value = onFulfilled(this.value);
// 根据onFulfilled函数的返回值来解析新Promise对象的状态
resolvePromise(newPromise, value);
} catch (err) {
// 如果onFulfilled函数抛出错误,则将新Promise对象的状态置为rejected
reject(err);
}
}
else if (this.state === 'rejected') {
// 使用try-catch块来捕获onRejected函数可能抛出的错误
try {
// 执行onRejected函数
const reason = onRejected(this.reason);
// 根据onRejected函数的返回值来解析新Promise对象的状态
resolvePromise(newPromise, reason);
} catch (err) {
// 如果onRejected函数抛出错误,则将新Promise对象的状态置为rejected
reject(err);
}
}
});
// 返回新创建的Promise对象
return newPromise;
}
resolve(value) {
// 检查Promise对象的状态是否为pending
if (this.state !== 'pending') {
return;
}
// 将Promise对象的状态置为fulfilled
this.state = 'fulfilled';
// 将Promise对象的值置为value
this.value = value;
// 执行onFulfilledCallbacks中存储的回调函数
this.onFulfilledCallbacks.forEach((callback) => {
callback();
});
}
reject(reason) {
// 检查Promise对象的状态是否为pending
if (this.state !== 'pending') {
return;
}
// 将Promise对象的状态置为rejected
this.state = 'rejected';
// 将Promise对象的原因置为reason
this.reason = reason;
// 执行onRejectedCallbacks中存储的回调函数
this.onRejectedCallbacks.forEach((callback) => {
callback();
});
}
}
// 解析Promise对象的状态
function resolvePromise(promise, x) {
// 如果promise和x是同一个对象,则抛出TypeError错误
if (promise === x) {
throw new TypeError('Cannot resolve a promise with itself');
}
// 如果x是一个Promise对象,则将x的状态传递给promise
if (x instanceof Promise) {
x.then(
(value) => {
resolvePromise(promise, value);
},
(reason) => {
promise.reject(reason);
}
);
}
// 如果x是一个thenable对象,则将x的状态传递给promise
else if (typeof x === 'object' || typeof x === 'function') {
// 尝试获取x的then方法
let then;
try {
then = x.then;
} catch (err) {
promise.reject(err);
return;
}
// 如果then是一个函数,则将x的状态传递给promise
if (typeof then === 'function') {
let called = false;
try {
// 使用try-catch块来捕获then函数可能抛出的错误
then.call(
x,
(y) => {
// 如果then函数被调用了两次以上,则抛出TypeError错误
if (called) {
return;
}
called = true;
resolvePromise(promise, y);
},
(r) => {
// 如果then函数被调用了两次以上,则抛出TypeError错误
if (called) {
return;
}
called = true;
promise.reject(r);
}
);
} catch (err) {
// 如果then函数抛出错误,则将promise的状态置为rejected
if (!called) {
promise.reject(err);
}
}
} else {
promise.resolve(x);
}
}
// 如果x是一个普通值,则将promise的状态置为fulfilled,并将x作为promise的值
else {
promise.resolve(x);