当我们处理异步操作时,我们经常需要进行一系列的操作,如请求数据、处理数据、渲染UI等。在过去,这些操作通常通过回调函数来处理,但是回调函数嵌套过多会导致代码难以维护,产生回调地狱(Callback Hell)。Promise就是一种用于解决异步编程问题的解决方案。
Promise是一种代表异步操作最终完成或失败的对象。它是ES6中新增的语法特性,通过Promise对象,可以更加优雅地处理异步操作。Promise有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。一旦Promise的状态发生改变,就不会再变。
如果要手写Promise,那就需要先理清楚重点,然后实现主,要集中在以下几个方面:
在知道Promise的概念以及重点之后,我们来简单实现一下:
class MyPromise {
constructor(executor) {
// 初始化Promise的状态为pending
this.state = 'pending';
// 存储Promise的成功值
this.value = undefined;
// 存储Promise的失败原因
this.reason = undefined;
// 存储成功状态下的回调函数数组
this.onResolvedCallbacks = [];
// 存储失败状态下的回调函数数组
this.onRejectedCallbacks = [];
// 定义resolve函数,用于将Promise状态从pending改变为fulfilled
const resolve = value => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
// 执行成功状态下的回调函数数组中的每个回调函数
this.onResolvedCallbacks.forEach(callback => callback());
}
};
// 定义reject函数,用于将Promise状态从pending改变为rejected
const reject = reason => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
// 执行失败状态下的回调函数数组中的每个回调函数
this.onRejectedCallbacks.forEach(callback => callback());
}
};
try {
// 执行executor函数,并将resolve和reject函数作为参数传递给executor
executor(resolve, reject);
} catch (error) {
// 如果executor执行过程中发生了错误,则将Promise状态改变为rejected
reject(error);
}
}
// then方法用于注册Promise的成功和失败回调,并返回一个新的Promise
then(onFulfilled, onRejected) {
// 创建一个新的Promise实例
const newPromise = new MyPromise((resolve, reject) => {
// 当前Promise的状态为fulfilled时
if (this.state === 'fulfilled') {
// 异步执行onFulfilled回调函数,并处理返回值result
setTimeout(() => {
try {
const result = onFulfilled(this.value);
// 将返回值result传递给resolvePromise函数,处理新Promise的状态
resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
// 如果执行onFulfilled回调函数过程中发生了错误,则将新Promise的状态改为rejected
reject(error);
}
}, 0);
}
// 当前Promise的状态为rejected时
if (this.state === 'rejected') {
// 异步执行onRejected回调函数,并处理返回值result
setTimeout(() => {
try {
const result = onRejected(this.reason);
// 将返回值result传递给resolvePromise函数,处理新Promise的状态
resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
// 如果执行onRejected回调函数过程中发生了错误,则将新Promise的状态改为rejected
reject(error);
}
}, 0);
}
// 当前Promise的状态为pending时
if (this.state === 'pending') {
// 将成功和失败回调函数分别添加到对应的回调函数数组中
this.onResolvedCallbacks.push(() => {
// 异步执行成功回调函数,并处理返回值result
setTimeout(() => {
try {
const result = onFulfilled(this.value);
// 将返回值result传递给resolvePromise函数,处理新Promise的状态
resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
// 如果执行成功回调函数过程中发生了错误,则将新Promise的状态改为rejected
reject(error);
}
}, 0);
});
this.onRejectedCallbacks.push(() => {
// 异步执行失败回调函数,并处理返回值result
setTimeout(() => {
try {
const result = onRejected(this.reason);
// 将返回值result传递给resolvePromise函数,处理新Promise的状态
resolvePromise(newPromise, result, resolve, reject);
} catch (error) {
// 如果执行失败回调函数过程中发生了错误,则将新Promise的状态改为rejected
reject(error);
}
}, 0);
});
}
});
// 返回新的Promise实例
return newPromise;
}
}
// resolvePromise函数用于处理then方法中回调函数返回的结果
function resolvePromise(newPromise, result, resolve, reject) {
// 如果新的Promise和返回值是同一个对象,则抛出错误
if (newPromise === result) {
return reject(new TypeError('Chaining cycle detected for promise'));
}
// 如果返回值是Promise实例,则等待该Promise的状态改变,并根据其状态决定新Promise的状态
if (result instanceof MyPromise) {
result.then(resolve, reject);
} else {
// 如果返回值不是Promise实例,则将返回值传递给resolve函数,将新Promise的状态改变为fulfilled
resolve(result);
}
}
这段代码实现了一个非常基础的Promise,主要有以下几个部分:
构造函数接受一个执行器函数作为参数,在构造函数内部定义了resolve和reject函数,并执行了执行器函数。执行器函数接受两个参数,分别是resolve和reject,它们分别用于将Promise状态从pending改变为fulfilled和rejected。
执行器函数中通过try...catch块捕获可能的异常,并在捕获到异常时将Promise状态改变为rejected。
then方法用于注册Promise的成功和失败回调,并返回一个新的Promise。它接受两个参数,分别是成功回调onFulfilled和失败回调onRejected。
在then方法内部,根据当前Promise的状态(pending、fulfilled、rejected),分别处理执行成功和执行失败的逻辑,并在异步环境下使用setTimeout确保执行顺序。
如果then方法中的回调函数返回了一个Promise,则等待该Promise的状态改变,并根据其状态决定新的Promise的状态。
resolvePromise函数:
resolvePromise函数用于处理then方法中回调函数返回的结果。如果结果是一个Promise,则等待该Promise的状态改变,并根据其状态决定新的Promise的状态。