文章目录
- 1.Promise基本使用
- 2.实现一个Promise
- 2.1.resolve/reject
- 2.1.1.初始化状态及返回值
- 2.1.2.实现resolve/reject
- 2.1.3.状态不可逆
- 2.1.4.处理throw
- 2.2.then
- 2.2.1.实现then
- 2.2.2.通过队列实现setTimeout
- 2.2.3.链式调用
- 2.2.4.执行顺序
- 2.3.其他方法
- 2.3.1.all
- 2.3.2.race
- 2.3.3.allsetled
- 2.3.4.any
- 3.最终代码
1.Promise基本使用
Promise
是一个构造函数- 通过
new
创建 - 接收一个拥有
resolve
、reject
两个参数的callback
let p1 = new Promise((resolve, reject) => {});
console.log("p1", p1);
let p2 = new Promise((resolve, reject) => {
resolve("success");
reject("error");
});
console.log("p2", p2);
let p3 = new Promise((resolve, reject) => {
reject("error");
resolve("success");
});
console.log("p3", p3);
let p4 = new Promise((resolve, reject) => {
throw "报错啦~";
});
console.log("p4", p4);
这里说明了 Promise
的五个特点:
- 初始化的时候,
Promise
状态为pending
; - 执行了
resolve
,Promise
状态会变成fulfilled
; - 执行了
reject
,Promise
状态会变成rejected
; Promise
状态不可逆,第一次成功就永久为fulfilled
,第一次失败就永远状态为rejected
;Promise
中有throw
的话,就相当于执行了reject
;
2.实现一个Promise
2.1.resolve/reject
2.1.1.初始化状态及返回值
- 初始状态为
pending
class myPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = undefined; // Promise 返回值
}
}
2.1.2.实现resolve/reject
new
的时候接收resolve
和reject
,并修改状态
class myPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
exector(this.resolve, this.reject);
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
}
resolve(value) {
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
}
reject(reason) {
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
}
}
测试:
let test = new myPromise((resolve, reject) => {
resolve("成功啦~");
reject("失败啦~");
});
console.log(test);
此时发现报错了,经过排查原因发现是 this 指向问题,当 new MyPromise 创建实例对象后,此时 test 上还没有绑定 resolve和reject方法;
增加一个 initBind
方法,用于初始化时将 this
绑定到实例对象上:
class myPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
exector(this.resolve, this.reject);
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
}
reject(reason) {
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
}
}
let test = new myPromise((resolve, reject) => {
resolve("成功啦~");
reject("失败啦~");
});
console.log(test);
测试:
let test = new myPromise((resolve, reject) => {
resolve("成功啦~");
reject("失败啦~");
});
此时已经可以正常执行了:
2.1.3.状态不可逆
我们知道原生的 Promise
状态是不可逆的,只能改变一次,预期只执行 resolve
, 但是这里也执行了 reject
,改造如下:
class myPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
exector(this.resolve, this.reject);
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
}
reject(reason) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
}
}
测试:
let test1 = new myPromise((resolve, reject) => {
resolve("成功啦test1~");
reject("失败啦test1~");
});
console.log(test1);
let test2 = new myPromise((resolve, reject) => {
reject("失败啦test2~");
resolve("成功啦test2~");
});
console.log(test2);
此时状态已不可逆:
2.1.4.处理throw
此时如果直接抛出错误,会怎么样呢?
let test3 = new myPromise((resolve, reject) => {
throw "报错啦test3~";
});
console.log(test3);
由原生 Promise
可以知道,如果直接抛出错误,那么状态和 reject
执行时一样,都是 rejected
,此时不满足预期的功能:
继续改造,增加 try catch
来处理异常:
class myPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
try {
// 正常执行的话,执行 exector
exector(this.resolve, this.reject);
} catch {
// 捕获到异常,则执行一次 reject
this.reject();
}
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
}
reject(reason) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
}
}
测试:
let test3 = new myPromise((resolve, reject) => {
throw "报错啦test3~";
});
console.log(test3);
此时已经满足了预期的功能:
2.2.then
平时业务中then的使用一般如下:
// 马上输出 -> "成功了"
const p1 = new Promise((resolve, reject) => {
resolve("成功了"); // 成功的话,执行 then 中的成功回调
}).then(
(res) => console.log(res),
(err) => console.log(err)
);
// 1秒后输出 -> "失败了"
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject("失败了"); // 失败的话执行 then 中的失败回调
}, 1000);
}).then(
(res) => console.log(res),
(err) => console.log(err)
);
// 链式调用 -> 输出 200
const p3 = new Promise((resolve, reject) => {
resolve(100); // 成功的话执行 then 中成功的回调
})
.then(
(res) => 2 * res,
(err) => console.log(err)
)
.then(
(res) => console.log(res),
(err) => console.log(err)
);
总结 then
的使用规则:
then
接收两个参数,一个是成功回调,一个是失败回调;- 状态为
fulfilled
时执行成功回调,状态为rejected
时执行失败回调; resolve
和reject
可以在定时器中,并且定时器时间结束后依次执行then
可以链式调用,上一次then
的返回值传递给下一个then
;
2.2.1.实现then
根据上面总结的规则,声明一个 then
函数:
class myPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
try {
// 正常执行的话,执行 exector
exector(this.resolve, this.reject);
} catch {
// 补货到异常,则执行一次 reject
this.reject();
}
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
}
reject(reason) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
}
then(onFulfilled, onRejected) {
// then 函数接收两个callback,一个是成功回调,一个是失败回调
// 参数兜底处理,确保返回的都是回调函数
onFulfilled = typeof onFulfilled === "Function" ? onFulfilled : (value) => value;
onRejected = typeof onRejected === "Function"
? onRejected
: (reason) => {
throw reason;
};
// 如果成功,则执行成功回调
// 如果失败,则执行失败回调
if (this.PromiseState === "fulfilled") {
onFulfilled(this.PromiseResult);
} else if (this.PromiseState === "rejected") {
onRejected(this.PromiseResult);
}
}
}
测试:
let test1 = new myPromise((resolve, reject) => {
resolve(10);
}).then(
(res) => console.log(res),
(err) => console.log(err)
);
then
的基本功能已实现:
2.2.2.通过队列实现setTimeout
下面的代码如何按预期的 1s 之后再执行呢?
// 1秒后输出 ”fail“
const p2 = new Promise((resolve, reject) => {
setTimeout(() => {
reject('fail')
}, 1000)
}).then(res => console.log(res), err => console.log(err))
- 我们不能保证 1s 之后才执行
then
,但是换个思路我们可以保证then
中的回调,1s之后再执行; - 在这 1s 中,可以先把
then
中的回调报错起来,等resolve
或者reject
执行之后,再去执行保存的回调函数。 - 只要执行
resolve
或者reject
那么状态就会发生变化,只需要在状态为pending
时使用一个数组将回调保存起来即可:
class myPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
try {
// 正常执行的话,执行 exector
exector(this.resolve, this.reject);
} catch {
// 补货到异常,则执行一次 reject
this.reject();
}
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
this.onFulfilledCallbacks = []; // 保存成功的回调
this.onRejectedCallbacks = []; // 保存失败的回调
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
// 执行成功的回调
while (this.onFulfilledCallbacks.length) {
// 每次从队列中取出一个来执行
this.onFulfilledCallbacks.shift()(this.PromiseResult);
}
}
reject(reason) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
// 执行成功的回调
while (this.onRejectedCallbacks.length) {
// 每次从队列中取出一个来执行
this.onRejectedCallbacks.shift()(this.PromiseResult);
}
}
then(onFulfilled, onRejected) {
// then 函数接收两个callback,一个是成功回调,一个是失败回调
// 参数兜底处理,确保返回的都是回调函数
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
// 如果成功,则执行成功回调
// 如果失败,则执行失败回调
if (this.PromiseState === "fulfilled") {
onFulfilled(this.PromiseResult);
} else if (this.PromiseState === "rejected") {
onRejected(this.PromiseResult);
} else if (this.PromiseState === "pending") {
// 将成功回调放入队列
this.onFulfilledCallbacks.push(onFulfilled);
// 将失败回调放入队列
this.onRejectedCallbacks.push(onRejected);
}
}
}
测试:
let test1 = new myPromise((resolve, reject) => {
setTimeout(() => {
resolve("成功回调test1");
}, 1000);
}).then(
(res) => console.log(res),
(err) => console.log(err)
);
let test2 = new myPromise((resolve, reject) => {
setTimeout(() => {
reject("失败回调test2");
}, 2000);
}).then(
(res) => console.log(res),
(err) => console.log(err)
);
1s 之后执行成功回调,2s 之后执行失败回调,此时是满足预期的:
2.2.3.链式调用
此时还有一个问题,原生 Promise
是支持链式调用的,并且上一次 then
的值会传递给下一次 then
,如下面这个例子:
// 链式调用 输出 200
const p3 = new Promise((resolve, reject) => {
resolve(100)
}).then(res => 2 * res, err => console.log(err))
.then(res => console.log(res), err => console.log(err))
// 链式调用 输出300
const p4 = new Promise((resolve, reject) => {
resolve(100)
}).then(res => new Promise((resolve, reject) => resolve(3 * res)), err => console.log(err))
.then(res => console.log(res), err => console.log(err))
而 MyPromise
目前还不支持。
为什么 Promise
能支持链式调用呢?
因为在 then
方法执行完成之后,返回值被包装成了一个 Promise
。
then
方法本身会返回一个新的Promise
对象;- 如果返回值是
promise
对象,返回值为成功,新promise
就是成功; - 如果返回值是
promise
对象,返回值为失败,新promise
就是失败; - 如果返回值非
promise
对象,新promise
对象就是成功,值为此返回值;
改造 MyPromise
:
class MyPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
try {
// 正常执行的话,执行 exector
exector(this.resolve, this.reject);
} catch (error) {
// 补货到异常,则执行一次 reject
this.reject(error);
}
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
this.onFulfilledCallbacks = []; // 保存成功的回调
this.onRejectedCallbacks = []; // 保存失败的回调
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
// 执行成功的回调
while (this.onFulfilledCallbacks.length) {
// 每次从队列中取出一个来执行
this.onFulfilledCallbacks.shift()(this.PromiseResult);
}
}
reject(reason) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
// 执行成功的回调
while (this.onRejectedCallbacks.length) {
// 每次从队列中取出一个来执行
this.onRejectedCallbacks.shift()(this.PromiseResult);
}
}
then(onFulfilled, onRejected) {
// then 函数接收两个callback,一个是成功回调,一个是失败回调
// 参数兜底处理,确保返回的都是回调函数
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
var promiseThen = new MyPromise((resolve, reject) => {
const handlePromise = (fn) => {
try {
let f = fn(this.PromiseResult);
if (f === promiseThen) {
// 不能返回自身
throw new Error("不能返回自身。。。");
}
if (f instanceof MyPromise) {
// 如果是 Promise 则执行对应的回调
f.then(resolve, reject);
} else {
// 如果不是 Promise 则直接成功
resolve(f);
}
} catch (error) {
// 处理报错, 预防一些边界情况
reject(error);
throw new Error(error);
}
};
// 如果成功,则执行成功回调
// 如果失败,则执行失败回调
if (this.PromiseState === "fulfilled") {
// onFulfilled(this.PromiseResult);
handlePromise(onFulfilled);
} else if (this.PromiseState === "rejected") {
// onRejected(this.PromiseResult);
handlePromise(onRejected);
} else if (this.PromiseState === "pending") {
// 将成功回调放入队列
this.onFulfilledCallbacks.push(handlePromise(onFulfilled));
// 将失败回调放入队列
this.onRejectedCallbacks.push(handlePromise(onRejected));
}
});
// 返回包装的 Promise
return promiseThen;
}
}
测试:
const test1 = new MyPromise((resolve, reject) => {
resolve(100);
})
.then(
(res) => 2 * res,
(err) => 3 * err
)
.then(
(res) => console.log("success", res),
(err) => console.log("fail", err)
);
const test2 = new MyPromise((resolve, reject) => {
resolve(100);
})
.then(
(res) => new MyPromise((resolve, reject) => reject(2 * res)),
(err) => new Promise((resolve, reject) => resolve(3 * err))
)
.then(
(res) => console.log("success", res),
(err) => console.log("fail", err)
);
2.2.4.执行顺序
then
是微任务,因此执行会晚于全局上下文,例如:
const p = new Promise((resolve, reject) => {
resolve(1)
}).then(res => console.log(res), err => console.log(err))
console.log(2)
// 输出顺序是 2 1
在我们的 MyPromise
中暂未实现该功能,此处可以通过 setTimeout
宏任务来将 then
异步执行:
class MyPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
try {
// 正常执行的话,执行 exector
exector(this.resolve, this.reject);
} catch (error) {
// 补货到异常,则执行一次 reject
this.reject(error);
}
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
this.onFulfilledCallbacks = []; // 保存成功的回调
this.onRejectedCallbacks = []; // 保存失败的回调
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
// 执行成功的回调
while (this.onFulfilledCallbacks.length) {
// 每次从队列中取出一个来执行
this.onFulfilledCallbacks.shift()(this.PromiseResult);
}
}
reject(reason) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将残敌进来的错误抛出
this.PromiseResult = reason;
// 执行成功的回调
while (this.onRejectedCallbacks.length) {
// 每次从队列中取出一个来执行
this.onRejectedCallbacks.shift()(this.PromiseResult);
}
}
then(onFulfilled, onRejected) {
// then 函数接收两个callback,一个是成功回调,一个是失败回调
// 参数兜底处理,确保返回的都是回调函数
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
var promiseThen = new MyPromise((resolve, reject) => {
const handlePromise = (fn) => {
setTimeout(() => {
try {
let f = fn(this.PromiseResult);
if (f === promiseThen) {
// 不能返回自身
throw new Error("不能返回自身。。。");
}
if (f instanceof MyPromise) {
// 如果是 Promise 则执行对应的回调
f.then(resolve, reject);
} else {
// 如果不是 Promise 则直接成功
resolve(f);
}
} catch (error) {
// 处理报错, 预防一些边界情况
reject(error);
throw new Error(error);
}
});
};
// 如果成功,则执行成功回调
// 如果失败,则执行失败回调
if (this.PromiseState === "fulfilled") {
// onFulfilled(this.PromiseResult);
handlePromise(onFulfilled);
} else if (this.PromiseState === "rejected") {
// onRejected(this.PromiseResult);
handlePromise(onRejected);
} else if (this.PromiseState === "pending") {
// 将成功回调放入队列
this.onFulfilledCallbacks.push(handlePromise.bind(this, onFulfilled));
// 将失败回调放入队列
this.onRejectedCallbacks.push(handlePromise.bind(this, onRejected));
}
});
// 返回包装的 Promise
return promiseThen;
}
}
测试:
const p = new MyPromise((resolve, reject) => {
resolve(1);
}).then(
(res) => console.log(res),
(err) => console.log(err)
);
console.log(2);
2.3.其他方法
2.3.1.all
Promise.all()
总结:
- 接收一个
Promise
数组,如果参数不是Promise
则当做成功; - 如果所有的
Promise
都成功,则返回成功的结果数组; - 如果有一个
Promise
不成功,则返回这一次的失败结果;
static all(promises) {
const result = []; // 都成功后会被返回的数组
let count = 0; // 统计成功的次数
return new MyPromise((resolve, reject) => {
const addData = (index, value) => {
result[index] = value;
count++; // 成功一次则自增
if (count === promises.length) {
resolve(result);
}
};
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
// 如果是 Promise,则链式调用将参数传递下去
promise.then( (res) => {
addData(index, res);
},
(err) => reject(err)
);
} else {
// 不是 Promise 也当做成功状态
addData(index, promise);
}
});
});
}
测试:
const p1 = new MyPromise((resolve, reject) => {
resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
resolve(2);
});
const p3 = 3;
MyPromise.all([p1, p2, p3]).then((res) => {
console.log(res);
});
2.3.2.race
Promise.race()
总结:
- 接收一个
Promise
数组,如果参数不是Promise
则当做成功; - 哪个
Promise
最快得到结果,就返回那个结果,无论成功失败;
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
// 是Promise,则调用 then ,无论成功/失败都返回
promise.then(
(res) => resolve(res),
(err) => reject(err)
);
} else {
// 不是Promise则直接返回
resolve(promise);
}
});
});
}
测试:
const p1 = new MyPromise((resolve, reject) => {
resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
reject(2);
});
const p3 = 3;
MyPromise.race([p1, p2, p3]).then((res) => {
console.log(res);
});
p3 先执行,因此返回 p3:
2.3.3.allsetled
Promise.allsetled()
总结:
- 接收一个
Promise
数组,如果参数不是Promise
则当做成功; - 把每一个Promise的结果,集合成数组后返回;
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
let addData = (status, value, index) => {
result[index] = {
status,
value,
};
count++;
if (count === promises.length) {
resolve(result);
}
};
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
// 记录状态,不管成功失败都返回
promise.then(
(res) => addData("fulfilled", res, index),
(err) => addData("rejected", err, index)
);
} else {
addData("fulfilled", promise, index);
}
});
});
}
测试:
const p1 = new MyPromise((resolve, reject) => {
resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
reject(2);
});
const p3 = 3;
MyPromise.allSettled([p1, p2, p3]).then((res) => {
console.log(res);
});
2.3.4.any
Promise.any()
总结:
- 接收一个
Promise
数组,如果参数不是Promise
则当做成功; - 如果有一个Promise成功,则返回这个成功结果;
- 如果所有Promise都失败,则报错;
static any(promises) {
return new MyPromise((resolve, reject) => {
let count = 0;
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(
(res) => resolve(res),
(err) => {
count++;
if (count === promises.length) {
reject("都执行失败了~");
}
}
);
}
});
});
}
测试:
const p1 = new MyPromise((resolve, reject) => {
resolve(1);
});
const p2 = new MyPromise((resolve, reject) => {
reject(2);
});
const p3 = 3;
MyPromise.any([p1, p2, p3]).then((res) => {
console.log(res);
});
有一个成功则返回成功的那一个 Promise
:
测试:
const p1 = new MyPromise((resolve, reject) => {
reject(1);
});
const p2 = new MyPromise((resolve, reject) => {
reject(2);
});
MyPromise.any([p1, p2]).then((res) => {
console.log(res);
});
错误数量和接收的数组长度一致,则抛出错误:
3.最终代码
class MyPromise {
constructor(exector) {
// 初始化状态及初始值
this.initValue();
// 初始化的时候改变 this 指向,将 this 指向实例对象
this.initBind();
// 执行器,当 new MyPromise()时,这个callback要接受 resolve 和 reject 函数
try {
// 正常执行的话,执行 exector
exector(this.resolve, this.reject);
} catch (error) {
// 捕获到异常,则执行一次 reject
this.reject(error);
}
}
initValue() {
this.PromiseState = "pending"; // Promise 状态
this.PromiseResult = null; // Promise 返回值
this.onFulfilledCallbacks = []; // 保存成功的回调
this.onRejectedCallbacks = []; // 保存失败的回调
}
initBind() {
this.resolve = this.resolve.bind(this);
this.reject = this.reject.bind(this);
}
resolve(value) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 fulfilled
this.PromiseState = "fulfilled";
// 将传递进来的参数赋值
this.PromiseResult = value;
// 执行成功的回调
while (this.onFulfilledCallbacks.length) {
// 每次从队列中取出一个来执行
this.onFulfilledCallbacks.shift()(this.PromiseResult);
}
}
reject(reason) {
// 只要状态已经改变,就不允许继续修改状态
if (this.PromiseState !== "pending") {
return;
}
// 此时状态改为 rejected
this.PromiseState = "rejected";
// 将传递进来的错误抛出
this.PromiseResult = reason;
// 执行成功的回调
while (this.onRejectedCallbacks.length) {
// 每次从队列中取出一个来执行
this.onRejectedCallbacks.shift()(this.PromiseResult);
}
}
then(onFulfilled, onRejected) {
// then 函数接收两个callback,一个是成功回调,一个是失败回调
// 参数兜底处理,确保返回的都是回调函数
onFulfilled =
typeof onFulfilled === "function" ? onFulfilled : (value) => value;
onRejected =
typeof onRejected === "function"
? onRejected
: (reason) => {
throw reason;
};
var promiseThen = new MyPromise((resolve, reject) => {
const handlePromise = (fn) => {
setTimeout(() => {
try {
let f = fn(this.PromiseResult);
if (f === promiseThen) {
// 不能返回自身
throw new Error("不能返回自身。。。");
}
if (f instanceof MyPromise) {
// 如果是 Promise 则执行对应的回调
f.then(resolve, reject);
} else {
// 如果不是 Promise 则直接成功
resolve(f);
}
} catch (error) {
// 处理报错, 预防一些边界情况
reject(error);
throw new Error(error);
}
});
};
// 如果成功,则执行成功回调
// 如果失败,则执行失败回调
if (this.PromiseState === "fulfilled") {
// onFulfilled(this.PromiseResult);
handlePromise(onFulfilled);
} else if (this.PromiseState === "rejected") {
// onRejected(this.PromiseResult);
handlePromise(onRejected);
} else if (this.PromiseState === "pending") {
// 将成功回调放入队列
this.onFulfilledCallbacks.push(handlePromise.bind(this, onFulfilled));
// 将失败回调放入队列
this.onRejectedCallbacks.push(handlePromise.bind(this, onRejected));
}
});
// 返回包装的 Promise
return promiseThen;
}
static all(promises) {
const result = [];
let count = 0;
return new MyPromise((resolve, reject) => {
const addData = (index, value) => {
result[index] = value;
count++;
if (count === promises.length) resolve(result);
};
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(
(res) => {
addData(index, res);
},
(err) => reject(err)
);
} else {
addData(index, promise);
}
});
});
}
static race(promises) {
return new MyPromise((resolve, reject) => {
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(
(res) => resolve(res),
(err) => reject(err)
);
} else {
resolve(promise);
}
});
});
}
static allSettled(promises) {
return new MyPromise((resolve, reject) => {
let result = [];
let count = 0;
let addData = (status, value, index) => {
result[index] = {
status,
value,
};
count++;
if (count === promises.length) {
resolve(result);
}
};
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(
(res) => addData("fulfilled", res, index),
(err) => addData("rejected", err, index)
);
} else {
addData("fulfilled", promise, index);
}
});
});
}
static any(promises) {
return new MyPromise((resolve, reject) => {
let count = 0;
promises.forEach((promise, index) => {
if (promise instanceof MyPromise) {
promise.then(
(res) => resolve(res),
(err) => {
count++;
if (count === promises.length) {
reject("都执行失败了~");
}
}
);
}
});
});
}
}