手写Promise机制前,我们先了解下来源。这个来源主要从promise a+ 这么一个规范而得的。我们从面试的角度上看,如果写这么一个上万行代码的规范,其实是不现实的。1、时间上面试一共1个多小时,不可能都放在这个方面,2、平时不会去手写,没必要。因为有现成的库和源码。那么接下来我们,来实现一个横扫面试的Promise机制。
class MyPromise {
state = "pending"; // pending fulfilled rejected
value = undefined;
reason = undefined;
resolveCallbacks = [];
rejectCallbacks = [];
constructor(fn) {
const resolveHandler = (value) => {
setTimeout(() => { //为了实现异步调用
if (this.state === "pending") {
this.state = "fulfilled";
this.value = value;
this.resolveCallbacks.forEach((fn) => fn(value));
}
});
};
const rejectHandler = (reason) => {
setTimeout(() => { //为了实现异步调用
if (this.state === "pending") {
this.state = "rejected";
this.reason = reason;
this.rejectCallbacks.forEach((fn) => fn(reason));
}
});
};
try {
fn(resolveHandler, rejectHandler);
} catch (err) {
rejectHandler(err);
}
}
then(fn1, fn2) {
fn1 = typeof fn1 === "function" ? fn1 : (v) => v;
fn2 = typeof fn2 === "function" ? fn2 : (e) => e;
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.rejectHandler.push(() => {
try {
const newReason = fn2(this.reason);
reject(newReason);
} catch (err) {
reject(err);
}
});
});
return p1;
}
if (this.state === "fulfilled") {
const p1 = new MyPromise((resolve, reject) => {
try {
const newValue = fn1(this.value);
resolve(newValue);
} catch (err) {
reject(err);
}
});
return p1;
}
if (this.state === "rejected") {
const p1 = new MyPromise((resolve, reject) => {
try {
const newReason = fn2(this.reason);
reject(newReason);
} catch (err) {
reject(err);
}
});
return p1;
}
}
//就是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 reasults = [];
const length = promiseList.length;
let resolveCount = 0;
promiseList.forEach((p) => {
p.then((data) => {
reasults.push(data);
resolveCount++;
if (resolveCount === length - 1) {
resolve(reasults);
}
}).catch((err) => {
reject(err);
});
});
});
return p1;
};
MyPromise.race = function (promiseList = []) {
const p1 = new MyPromise((resolve, reject) => {
let isResolved = false; //标记
promiseList.forEach((p) => {
p.then((data) => {
if (!isResolved) {
resolve(data);
isResolved = true;
}
}).catch((err) => {
reject(err);
});
});
});
return p1;
};
下面这个是如何验证,我们手写Promise机制的函数调用。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="./MyPromise.js"></script>
<script>
//初始化MyPromise类
const p1 = new MyPromise((resolve, reject) => {
//调用resolve函数
resolve(100)
//调用reject函数
reject('错误信息...')
//执行异步任务,验证函数回调
setTimeout(()=> {
console.log('1111')
}, 1000)
})
//链式调用,并且执行then函数
const p12 = p1.then((data) => {
console.log('data', data)
return data + 1
})
//链式调用,多次执行then函数
const p13 = p12.then((data) => {
console.log('data1', data)
return data + 1
})
//链式调用,执行catch函数
const p14 = p13.catch((err) => console.error('错误信息。。。'))
//静态方法执行resolve函数
const p2 = MyPromise.resolve(100)
const p3 = MyPromise.resolve(200)
//静态方法执行reject函数
const p4 = MyPromise.reject('错误信息...')
//传入 promise 数组,等待所有的都 fulfilled 之后,返回新 promise ,包含前面所有的结果
const p5 = MyPromise.all([p1, p2, p3])
p5.then((data)=> {console.log('all result', data)})
// 传入 promise 数组,只要有一个 fulfilled 即可返回
const p6 = MyPromise.race([p1,p2,p3])
p6.then((data) => {console.log('race result', data)})
</script>
</body>
</html>