手撸自己的Promise,Promise手写代码
在我们开始前,我们先对Promise进行一个了解,首先Promise是一个类,在执行这个类的时候需要传递一个执行器进去,并立即执行,执行器接受两个参数:resolve和reject两个方法;再有就是Promise有三种状态:等待pending、成功fullfilled和失败rejected;当然我们在使用Promise时,它还拥有then和catch方法;最后也需要实现Promise.resolve、Promise.resolve、Promise.all和Promise.race的实现。
-
首先我们创建一个MyPromise.html文件,将所用到的情况都写下来,便于我们写Promise时避免遗漏和方便测试和编写
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>MyPromise</title> </head> <body> <h1>MyPromise</h1> <script src="./MyPromise.js"></script> <script> const p1 = new MyPromise((resolve, reject) => { // resolve(100); setTimeout(() => { resolve(100); }, 1000); }); p1.then((data1) => { return data1 + 1; }) .then((data2) => { return data2 + 2; }) .catch((err) => { console.log(err); }); const p2 = MyPromise.resolve(200); const p3 = MyPromise.reject(300); const p4 = MyPromise.all([p1, p2]); const p5 = MyPromise.race([p2, p3]); console.log(p5); </script> </body> </html>
-
我们创建MyPromise.js的文件并创建类MyPromise
/** * @description MyPromise * @author gsx */ class MyPromise { };
-
根据对Promise的描述我们定义好一些属性和方法
/** * @description MyPromise * @author gsx */ class MyPromise { state = "pending"; //状态 pending fulfilled rejected value = undefined; // 成功后的值 reason = undefined; // 失败后的原因 resolveCallbacks = []; // padding状态下 成功回调 rejectCallbacks = []; // padding状态下 失败回调 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 (error) { rejectHandler(error); } } then(fn1, fn2) { // 当pending状态下,fn1 fn2 会被储存到callbacks中 } // 就是then的一个语法糖 catch(fn) { return this.then(null, fn); } }
-
接下来我们来完成then
/** * @description MyPromise * @author gsx */ class MyPromise { ... then(fn1, fn2) { // 当pending状态下,fn1 fn2 会被储存到callbacks中 fn1 = typeof fn1 === "function" ? fn1 : (value) => value; fn2 = typeof fn2 === "function" ? fn2 : (error) => error; if (this.state === "pending") { return new MyPromise((resolve, reject) => { this.resolveCallbacks.push(() => { try { const result = fn1(this.value); resolve(result); } catch (error) { reject(error); } }); this.rejectCallbacks.push(() => { try { const result = fn1(this.reason); reject(result); } catch (error) { reject(error); } }); }); } if (this.state === "fulfilled") { return new MyPromise((resolve, reject) => { try { const result = fn1(this.value); resolve(result); } catch (error) { reject(error); } }); } if (this.state === "rejected") { return new MyPromise((__, reject) => { try { const result = fn2(this.reason); reject(result); } catch (error) { reject(error); } }); } } // 就是then的一个语法糖 catch(fn) { return this.then(null, fn); } }
-
完成resolve、reject、all、race
/** * @description MyPromise * @author gsx */ class MyPromise { ... } MyPromise.resolve = function (value) { return new MyPromise((resolve) => { resolve(value); }); }; MyPromise.reject = function (reason) { return new MyPromise((__, reject) => { reject(reason); }); }; MyPromise.all = function (promiseList = []) { return new MyPromise((resolve, reject) => { const result = []; // 存储结果 const length = promiseList.length; let resolvedCount = 0; promiseList.forEach((promise, index) => { promise .then((value) => { result[index] = value; resolvedCount++; if (resolvedCount === length) { resolve(result); } }) .catch((error) => { reject(error); }); }); }); }; MyPromise.race = function (promiseList = []) { return new MyPromise((resolve, reject) => { let resolved = false; promiseList.forEach((promise) => { promise .then((value) => { if (!resolved) { resolved = true; resolve(value); } }) .catch((error) => { reject(error); }); }); }); };
完整代码
/**
* @description MyPromise
* @author gsx
*/
class MyPromise {
state = "pending"; //状态 pending fulfilled rejected
value = undefined; // 成功后的值
reason = undefined; // 失败后的原因
resolveCallbacks = []; // padding状态下 成功回调
rejectCallbacks = []; // padding状态下 失败回调
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 (error) {
rejectHandler(error);
}
}
then(fn1, fn2) {
// 当pending状态下,fn1 fn2 会被储存到callbacks中
fn1 = typeof fn1 === "function" ? fn1 : (value) => value;
fn2 = typeof fn2 === "function" ? fn2 : (error) => error;
if (this.state === "pending") {
return new MyPromise((resolve, reject) => {
this.resolveCallbacks.push(() => {
try {
const result = fn1(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
this.rejectCallbacks.push(() => {
try {
const result = fn1(this.reason);
reject(result);
} catch (error) {
reject(error);
}
});
});
}
if (this.state === "fulfilled") {
return new MyPromise((resolve, reject) => {
try {
const result = fn1(this.value);
resolve(result);
} catch (error) {
reject(error);
}
});
}
if (this.state === "rejected") {
return new MyPromise((__, reject) => {
try {
const result = fn2(this.reason);
reject(result);
} catch (error) {
reject(error);
}
});
}
}
// 就是then的一个语法糖
catch(fn) {
return this.then(null, fn);
}
}
MyPromise.resolve = function (value) {
return new MyPromise((resolve) => {
resolve(value);
});
};
MyPromise.reject = function (reason) {
return new MyPromise((__, reject) => {
reject(reason);
});
};
MyPromise.all = function (promiseList = []) {
return new MyPromise((resolve, reject) => {
const result = []; // 存储结果
const length = promiseList.length;
let resolvedCount = 0;
promiseList.forEach((promise, index) => {
promise
.then((value) => {
result[index] = value;
resolvedCount++;
if (resolvedCount === length) {
resolve(result);
}
})
.catch((error) => {
reject(error);
});
});
});
};
MyPromise.race = function (promiseList = []) {
return new MyPromise((resolve, reject) => {
let resolved = false;
promiseList.forEach((promise) => {
promise
.then((value) => {
if (!resolved) {
resolved = true;
resolve(value);
}
})
.catch((error) => {
reject(error);
});
});
});
};
快试试吧!