手动实现一个简单的 Promise 使得我们对 Promise 的深入理解,但是实现一个 Promise 会有哪些需求呢?
理解自定义 Promise 的需求
- 一个构造函数,内部定义 Promise 的状态 pending/fulfilled/rejected 等相关数据。
- 构造函数中参数执行器,执行器在实例化 Promise 的时候就开始执行。
- then 方法,参数是两个函数,第一个是
成功
调用的方法,第二个是失败
调用的方法。返回值是新
的 Promise。 - 状态转换。如果成功时,需要执行成功的回调,然后将状态
pending ->fulfilled
。如果失败时,需要执行失败回调,然后将状态pending->rejected
函数。 - 异步实现。异步一般使用 setTimeout 和 setImmediate 或者其他的异步方案来实现即可。
- 链式调用。then 种返回一个 Promise 即可。
- 错误处理。链式调用的 catch 方法 或者 then 方法中的第二个函数。
- 值(错误)传递。在状态转换的时候需要正确传递值和拒绝的原因。
- 其他的方法。 Promise 还实现了很多其他的方法,更具需求自己实现。
构造函数
添加构造函数,并定义初始状态属性:
ts
class MyPromise {
constructor() {
this.state = 'pending';
}
}
添加 Promise 的执行
ts
class MyPromise {
constructor(executor) {
this.state = 'pending';
}
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
在内定义 executor 的参数决策成功和失败的函数
ts
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.error = undefined;
this.onFulfilled = [];
this.onRejected = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilled.forEach((callback) => callback(this.value));
}
};
const reject = (error) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.error = error;
this.onRejected.forEach((callback) => callback(this.error));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
}
- 决策成功的函数
resolve
调用将 state 转变成fulfilled
, resolve 决策的值时保存在 value 种,然后将 onFulfilled 中保存的函数,全部重新调用一次。onFulfilled 时值得关注 onFulfilled 数组中。 - 决策失败的函数
reject
调用将 state 转换成rejected
。将 错误保存起来,然后遍历 onRejected 数组将所有函数执行一次。
在 Promise 示例化之后, 执行器 executor 需要立即执行。
then 方法
then 的逻辑是返回 新的 Promise
ts
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
} else if (this.state === 'rejected') {
try {
const result = onRejected(this.error);
resolve(result);
} catch (error) {
reject(error);
}
} else {
this.onFulfilled.push((value) => {
try {
const result = onFulfilled(value);
resolve(result);
} catch (error) {
reject(error);
}
});
this.onRejected.push((error) => {
try {
const result = onRejected(error);
resolve(result);
} catch (error) {
reject(error);
}
});
}
});
}
测试用例
ts
const p = new MyPromise((resolve, reject) => {
setTimeout(() => {
resolve('success');
}, 1000);
}
)
p.then((r) => {
console.log(r)
}, (e) => {
console.log(e)
})
const pe = new MyPromise((resolve, reject) => {
setTimeout(() => {
reject('error');
}, 1000);
}
)
pe.then((r) => {
console.log(r)
}, (e) => {
console.error("error", e)
})
完整实现
ts
class MyPromise {
constructor(executor) {
this.state = 'pending';
this.value = undefined;
this.error = undefined;
this.onFulfilled = [];
this.onRejected = [];
const resolve = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
this.onFulfilled.forEach((callback) => callback(this.value));
}
};
const reject = (error) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.error = error;
this.onRejected.forEach((callback) => callback(this.error));
}
};
try {
executor(resolve, reject);
} catch (error) {
reject(error);
}
}
then(onFulfilled, onRejected) {
return new MyPromise((resolve, reject) => {
if (this.state === 'fulfilled') {
try {
const result = onFulfilled(this.value);
resolve(result);
} catch (error) {
reject(error);
}
} else if (this.state === 'rejected') {
try {
const result = onRejected(this.error);
resolve(result);
} catch (error) {
reject(error);
}
} else {
this.onFulfilled.push((value) => {
try {
const result = onFulfilled(value);
resolve(result);
} catch (error) {
reject(error);
}
});
this.onRejected.push((error) => {
try {
const result = onRejected(error);
resolve(result);
} catch (error) {
reject(error);
}
});
}
});
}
catch(onRejected) {
return this.then(null, onRejected);
}
}
小结
手动实现简单的 Promise, 关键在于理解 Promise 设计的业务模型,Promise 的实例化开始立即执行器中的函数 executor, 在内部定义 Promise 的状态,定义 Promise 所需要的执行器函数,已经在执行函数内部定义 resolve 和 reject
函数,最后还需要定义两个特殊的数组来处理进入 then 之后还是 pendding 状态处理函数,然后在角色之后遍历此数组接口。Promise 基本实现 then 方法以及 then 方法的链式调用,实现基本的 catch, catch 本质是一个特殊的 then 方法,只实现了 onRejected 部分。