手写 Promise
实现 promise 常用方法
- 初始化 & 异步调用
- then catch 链式调用
- 实现 API: .resolve .reject .all .race
代码实现 MyPromise
js
class MyPromise {
state = 'pending'; //状态 pending,fulfilled,rejected
value = undefined; // 成功后的值
reason = undefined; // 失败后的原因
resolveCallbacks = []; // pending 下,存储成功的回调
rejectCallbacks = []; // pending 下,存储失败的回调
constructor(fn) {
const resolveHandler = (value) => {
if (this.state === 'pending') {
this.state = 'fulfilled';
this.value = value;
// 状态变化后,函数执行
this.resolveCallbacks.forEach((fn) => fn(this.value));
}
};
const rejectHandler = (reason) => {
if (this.state === 'pending') {
this.state = 'rejected';
this.reason = reason;
// 状态变化后,函数执行
this.rejectCallbacks.forEach((fn) => fn(this.reason));
}
};
try {
fn(resolveHandler, rejectHandler);
} catch (err) {
resolveHandler(err);
}
}
then(fn1, fn2) {
// 当 pending 下,fn1,fn2 存储到 callbacks 中
fn1 = typeof fn1 === 'function' ? fn1 : (v) => v;
fn2 = typeof fn2 === 'function' ? fn2 : (e) => e;
// 函数还没执行,返回新的 promise
if (this.state === 'pending') {
const p1 = new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const newValue = fn1(this.value);
resolve(newValue);
} catch (err) {
reject(err);
}
});
this.rejectCallbacks.push(() => {
try {
const newReason = fn1(this.reason);
reject(newReason);
} catch (err) {
reject(err);
}
});
});
return p1;
}
// fn1 函数执行,返回新的 promise
if (this.state === 'fulfilled') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value);
resolve(newValue);
} catch (err) {
reject(err);
}
});
return p1;
}
// fn2 函数执行,返回新的 promise
if (this.state === 'rejected') {
const p1 = new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason);
reject(newReason);
} catch (err) {
reject(err);
}
});
return p1;
}
}
// catch 就是 then 的一个语法糖,简单模式
catch(fn) {
return this.then(null, fn);
}
}
// 全局静态方法
MyPromise.resolve = function (value) {
return new MyPromise((resolve, reject) => resolve(value));
};
MyPromise.reject = function (reason) {
return new MyPromise((resolve, reject) => reject(reason));
};
MyPromise.all = function (promiseList = []) {
const p1 = new MyPromise((resolve, reject) => {
const result = []; // 存储 promiseList 所有的结果
const length = promiseList.length;
let resolvedCount = 0;
promiseList.forEach((p) => {
p.then((data) => {
result.push(data);
// resolvedCount 必须在 then 里面做 ++
// 不能使用 foreach 的 index,因为 index 是同步的
resolvedCount++;
if (resolvedCount == length) {
// 已经到最后一个
resolve(result);
}
}).catch((err) => {
reject(err);
});
});
});
return p1;
};
MyPromise.race = function (promiseList = []) {
let resolved = false; // 标记
const p1 = new MyPromise((resolve, reject) => {
promiseList.forEach((p) => {
p.then((data) => {
if (!resolved) {
resolve(data);
resolved = true;
}
}).catch((err) => {
reject(err);
});
});
});
return p1;
};
测试代码
js
// 普通调用
const p1 = new MyPromise((resolve, reject) => {
// resolve(100)
// reject('错误...')
setTimeout(() => {
resolve(100);
}, 1000);
});
// 链式调用
const p11 = p1.then((data1) => {
console.log('data1', data1); // data1 100
return data1 + 1;
});
const p12 = p11.then((data2) => {
console.log('data2', data2); // data2 101
return data2 + 1;
});
const p13 = p12.catch((err) => console.error(err));
// api 调用
const p2 = MyPromise.resolve(200);
const p3 = MyPromise.resolve(300);
const p4 = MyPromise.reject('错误...');
// 传入 promise 数组,等待所有的都 fulfilled 后,返回新的 promise 包含前面所有的结果
const p5 = MyPromise.all([p1, p2, p3]);
p5.then((result) => console.log('all result', result)); // all result (3)[200, 300, 100]
// 传入 promise 数组,只要有一个 fulfilled 即可返回
const p6 = MyPromise.race([p1, p2, p3]);
p6.then((result) => console.log('race result', result)); // race result 200