Promise
先来个手撕Promise
// 先定义三个常量表示状态
const PENDING = "pending";
const FULFILLED = "fulfilled";
const REJECTED = "rejected";
class MyPromise {
constructor(executor) {
//executor 是一个执行器,进入会立即执行
try {
executor(this.resolve, this.reject);
} catch (error) {
this.reject(error);
}
}
//初始化变量
status = PENDING;
value = null; //成功
reason = null; //失败
// 存储成功回调函数
onFulfilledCallbacks = [];
// 存储失败回调函数
onRejectedCallbacks = [];
// resolve和reject为什么要用箭头函数?
// 如果直接调用的话,普通函数this指向的是window或者undefined
// 用箭头函数就可以让this指向当前实例对象
// 更改成功后的状态
resolve = value => {
if (this.status === PENDING) {
this.value = value;
this.status = FULFILLED;
// 判断成功回调是否存在,如果存在就调用
while (this.onFulfilledCallbacks.length) {
// Array.shift() 取出数组第一个元素,然后()调用,
// shift不是纯函数,取出后,数组将失去该元素,直到数组为空
this.onFulfilledCallbacks.shift()(value);
}
}
};
// 更改失败后的状态
reject = reason => {
if (this.status === PENDING) {
this.reason = reason;
this.status = REJECTED;
// 判断失败回调是否存在,如果存在就调用
while (this.onRejectedCallbacks.length) {
this.onRejectedCallbacks.shift()(reason);
}
}
};
then(onFulfilled, onRejected) {
// 如果不传,就使用默认函数
onFulfilled = typeof onFulfilled === "function" ? onFulfilled : value => value;
onRejected =
typeof onRejected === "function"
? onRejected
: reason => {
throw reason;
};
// 为了链式调用这里直接创建一个 MyPromise,并在后面 return 出去
const promise2 = new MyPromise((resolve, reject) => {
const fulfilledMicrotask = () => {
// 创建一个微任务等待 promise2 完成初始化
queueMicrotask(() => {
try {
// 获取成功回调函数的执行结果
const x = onFulfilled(this.value);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
const rejectedMicrotask = () => {
// 创建一个微任务等待 promise2 完成初始化
queueMicrotask(() => {
try {
// 调用失败回调,并且把原因返回
const x = realOnRejected(this.reason);
// 传入 resolvePromise 集中处理
resolvePromise(promise2, x, resolve, reject);
} catch (error) {
reject(error);
}
});
};
// 判断状态
if (this.status === FULFILLED) {
fulfilledMicrotask();
} else if (this.status === REJECTED) {
rejectedMicrotask();
} else if (this.status === PENDING) {
// 等待
// 因为不知道后面状态的变化情况,所以将成功回调和失败回调存储起来
// 等到执行成功失败函数的时候再传递
this.onFulfilledCallbacks.push(fulfilledMicrotask);
this.onRejectedCallbacks.push(rejectedMicrotask);
}
});
return promise2;
}
// resolve 静态方法
static resolve(parameter) {
//如果传入是 MyPromise 就直接返回
if (parameter instanceof MyPromise) {
return parameter;
}
//否则返回个 MyPromise 包着它
return new MyPromise(resolve => {
resolve(parameter);
});
}
// reject 静态方法
static reject(reason) {
return new MyPromise((resolve, reject) => {
reject(reason);
});
}
}
//解析
function resolvePromise(promise, x, resolve, reject) {
if (promise == x) {
return reject(new TypeError("Chaining cycle detected for promise #<Promise>"));
}
//判断 x 是不是 MyPromise 实例对象
if (x instanceof MyPromise) {
//如果是则表示x为 promise ,
//执行 x ,调用 then 方法,目的是将其状态变为 fulfilled或者rejected
//x.then(value => resolve(value),reason => reject(reason))
x.then(resolve, reject);
} else {
//普通值
resolve(x);
}
}
/* const promise = new MyPromise((resolve, reject) => {
resolve("success");
});
// 这个时候将promise定义一个p1,然后返回的时候返回p1这个promise
const p1 = promise.then(value => {
console.log(1);
console.log("resolve", value);
return p1;
});
// 运行的时候会走reject
p1.then(
value => {
console.log(2);
console.log("resolve", value);
},
reason => {
console.log(3);
console.log(reason.message);
}
); */
// promise
// .then(value => {
// console.log(1);
// console.log("resolve", value);
// return other();
// })
// .then(value => {
// console.log(2);
// console.log("resolve", value);
// });
// 第一个then方法中的错误要在第二个then方法中捕获到
/* promise
.then(
value => {
console.log(1);
console.log("resolve", value);
throw new Error("then error");
},
reason => {
console.log(2);
console.log(reason.message);
}
)
.then(
value => {
console.log(3);
console.log(value);
},
reason => {
console.log(4);
console.log(reason.message);
}
); */
// promise.then().then().then(value => console.log(value))
MyPromise.resolve()
.then(() => {
console.log(0);
return MyPromise.resolve(4);
})
.then(res => {
console.log(res);
});
- Promise.all:有 rejected ==会直接返回并且只返回这个rejected==,否则等全部返回
- Promise.allSettled(都解决的):全部执行完再返回,返回值里有 status [ "fulfilled" 或 "rejected" ]
- Promise.race(竞速的):返回第一个执行完的,不论是否 rejected
- Promise.any:返回第一个成功的,如果全部失败会进 catch 以上方法参数中有非 promise情况 则按成功状态处理
Promise.all
/**
* @description
* 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
* 如果所有Promise都成功,则返回成功结果数组
* 如果有一个Promise失败,则返回这个失败结果
* @param
* @author lg
* @date 2022-02-13 13:40:19
*/
function promiseAll(args) {
const promises = Array.from(args);
const len = promises.length;
let count = 0;
let resultList = [];
// 将三个promise存到一个大的promise中,异步等待执行
return new Promise((resolve, reject) => {
/**
* @param result: promise 结果
* @param index: promise 顺序
*/
function addToResultList(result, index) {
count++;
resultList[index] = result;
if (count === len) {
resolve(resultList);
}
}
promises.forEach((promise, index) => {
//如果数组里面是都是promise实例
if (promise instanceof Promise) {
promise.then(result => {
addToResultList(result, index);
}, reject);
} else {
//数组中有非Promise实例,此项当做成功;
addToResultList(promise, index);
}
});
});
}
let pro1 = Promise.resolve(1);
let pro2 = 2;
let pro3 = Promise.resolve(3);
promiseAll([pro1, pro2, pro3])
.then(data => {
console.log("result", data);
})
.catch(err => {
console.log("err", err);
});
Promise.allSettled
/**
* @description
* 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
* 把每一个Promise的结果,集合成数组,返回
* @param
* @author lg
* @date 2022-02-13 13:49:59
*/
function promiseAllSettled(args) {
const promises = Array.from(args);
const resultList = [];
const len = promises.length;
let count = 0;
return new Promise((resolve, reject) => {
if (len === 0) {
resolve(resultList);
}
/**
* @param result: promise 结果
* @param index: promise 顺序
*/
function addToResultList(result, index) {
count++;
resultList[index] = result;
if (count === len) {
resolve(resultList);
}
}
promises.forEach((promise, index) => {
if (promise instanceof Promise) {
promise.then(
res => {
addToResultList(
{
status: "fulfilled",
value: res
},
index
);
},
err => {
addToResultList(
{
status: "rejected",
reason: err
},
index
);
}
);
} else {
addToResultList(
{
status: "fulfilled",
value: promise
},
index
);
}
});
});
}
const p1 = Promise.resolve(1);
const p2 = new Promise(resolve => {
setTimeout(() => resolve(2), 1000);
});
const p3 = new Promise(resolve => {
setTimeout(() => resolve(3), 3000);
});
const p4 = Promise.reject("err4");
const p5 = Promise.reject("err5");
const p11 = promiseAllSettled([p1, p2, p4]).then(res =>
console.log(JSON.stringify(res, null, 2))
);
Promise.race
/**
* @description
* 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
* 哪个Promise最快得到结果,就返回那个结果,无论成功失败
* @param
* @author lg
* @date 2022-02-13 13:42:44
*/
function promiseRace(args) {
const promises = Array.from(args); //如果参数不是数组,转成数组
return new Promise((resolve, reject) => {
promises.forEach(promise => {
if (promise instanceof Promise) {
//谁先有结果就返回那个结果,无论成功失败
promise.then(
res => {
resolve(res);
},
err => {
reject(err);
}
);
} else {
resolve(promise);
}
});
});
}
let pro1 = Promise.resolve(1);
let pro2 = 2;
let pro3 = Promise.resolve(3);
promiseRace([pro1, pro2, pro3])
.then(data => {
console.log("result", data);
})
.catch(err => {
console.log("err", err);
});
Promise.any
/**
* @description
* 接收一个Promise数组,数组中如有非Promise项,则此项当做成功
* 如果有一个Promise成功,则返回这个成功结果
* 如果所有Promise都失败,则报错
* @param
* @author lg
* @date 2022-02-13 17:17:34
*/
function promiseAny(args) {
const promises = Array.from(args);
const len = promises.length;
let count = 0;
return new Promise((resolve, reject) => {
if (len === 0) return resolve([]);
promises.forEach(promise => {
if (promise instanceof Promise) {
promise.then(
res => {
resolve(res);
},
err => {
count++;
if (count === len) reject("All promises were rejected");
}
);
} else {
resolve(promise);
}
});
});
}
let pro1 = Promise.reject(1);
let pro2 = Promise.reject(1);
let pro3 = Promise.reject(3);
promiseAny([pro1, pro2, pro3])
.then(value => {
console.log("value: ", value);
})
.catch(err => {
console.log("err: ", err);
});