Promise 思维导图
1. resolve与reject
Promise的初始状态是pendingresolve和reject的this指向永远指向当前的MyPromise实例,防止随着函数执行环境的改变而改变代码
class MyPromise {constructor(executor) {this.initValue(); //初始化值this.initBind(); //初始化this指向executor(this.resolve, this.reject); //执行传进的函数}initBind() {this.resolve = this.resolve.bind(this);this.reject = this.reject.bind(this);}initValue() {this.promiseState = "pending";this.promiseResult = null;}resolve(value) {this.promiseState = "fulfilled";this.promiseResult = value;}reject(reason) {this.promiseState = "rejected";this.promiseResult = reason;}}
测试
```javascript const test1 = new MyPromise((resolve, reject) => { resolve(“ok”); }); test1;
const test2 = new MyPromise((resolve, reject) => { reject(“no”); }); test2;
<a name="SDpJD"></a># 2. 状态只可变一次```javascriptresolve(value) {if (this.PromiseState !== "pending") return;this.promiseState = "fulfilled";this.promiseResult = value;}reject(reason) {if (this.PromiseState !== "pending") return;this.promiseState = "rejected";this.promiseResult = reason;}
3. throw
有抛出错误就等于执行 reject,用 try catch 包裹一下
constructor(executor) {this.initValue(); //初始化值this.initBind(); //初始化this指向try {executor(this.resolve, this.reject); //执行传进的函数} catch (e) {this.reject(e);}}
4. then
- then接收两个回调,一个是成功回调,一个是失败回调
- 当Promise状态为fulfilled执行成功回调,为rejected执行失败回调
- 如resolve或reject在定时器里,则定时器结束后再执行then
- then支持链式调用,下一次then执行受上一次then返回值的影响
then(onFulfilled, onRejected) {// 参数校验,确保一定是函数onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;// console.log(onFulfilled);onRejected =typeof onRejected === "function"? onRejected: reason => {throw reason;};if (this.promiseState === "fulfilled") {// 如果当前为成功状态,执行第一个回调onFulfilled(this.promiseResult);} else if (this.promiseState === "rejected") {// 如果当前为失败状态,执行第二哥回调onRejected(this.promiseResult);}}
const test = new MyPromise((resolve, reject) => {resolve("ok");}).then(res => console.log(res),err => console.log(err));//ok
5. 定时器
如何保证有定时器的情况下,到规定的时间再执行回调?
我们可以正常执行 then 但是等到规定时间之后在执行 then 的回调
- 怎么知道要执行回调 —— 怎么知道什么时候定时器结束 —— pending 状态转变为其他状态的时候
- 一个 promise 可能有多个 then —— 用数组存
initValue() {this.promiseState = "pending";this.promiseResult = null;this.onFulfilledCallbacks = [];this.onRejectedCallbacks = [];}
resolve(value) {if (this.promiseState !== "pending") return;this.promiseState = "fulfilled";this.promiseResult = value;while (this.onFulfilledCallbacks.length) {this.onFulfilledCallbacks.shift()(this.promiseResult);}}reject(reason) {if (this.promiseState !== "pending") return;this.promiseState = "rejected";this.promiseResult = reason;while (this.onRejectedCallbacks.length) {this.onRejectedCallbacks.shift()(this.promiseResult);}}
then(onFulfilled, onRejected) {// 参数校验,确保一定是函数onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;// console.log(onFulfilled);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") {//状态仍是 pending,先保存this.onFulfilledCallbacks.push(onFulfilled.bind(this));this.onRejectedCallbacks.push(onRejected.bind(this));}}
测试
const test2 = new MyPromise((resolve, reject) => {setTimeout(() => {resolve("成功"); // 1秒后输出 成功// resolve('成功') // 1秒后输出 失败}, 1000);}).then(res => console.log(res),err => console.log(err));
6. 链式调用
下一次then执行受上一次then返回值的影响
then方法本身会返回一个新的Promise对象- 如果返回值是
promise对象,返回值为成功,新promise就是成功 - 如果返回值是
promise对象,返回值为失败,新promise就是失败 - 如果返回值非
promise对象,新promise对象就是成功,值为此返回值
then(onFulfilled, onRejected) {// 参数校验,确保一定是函数onFulfilled = typeof onFulfilled === "function" ? onFulfilled : val => val;// console.log(onFulfilled);onRejected =typeof onRejected === "function"? onRejected: reason => {throw reason;};const thenPromise = new MyPromise((resolve, reject) => {const resolvePromise = cb => {try {const x = cb(this.promiseResult);if (x === thenPromise) {throw new Error("不能返回自身");}if (x instanceof MyPromise) {x.then(resolve, reject);} else {//不是 promise 对象resolve(x);}} catch (e) {reject(e);throw new Error(e);}};if (this.promiseState === "fulfilled") {// 如果当前为成功状态,执行第一个回调resolvePromise(onFulfilled);} else if (this.promiseState === "rejected") {// 如果当前为失败状态,执行第二个回调resolvePromise(onRejected);} else if (this.promiseState === "pending") {//状态仍是 pending,先保存this.onFulfilledCallbacks.push(resolvePromise.bind(this, onFulfilled));this.onRejectedCallbacks.push(resolvePromise.bind(this, onRejected));}});return thenPromise;}}
7. 微任务
8. 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.then(res => {addData(index, res);},err => reject(err));} else {addData(index, promise);}});});}
9. race
接收一个
Promise数组,数组中如有非Promise项,则此项当做成功哪个
Promise最快得到结果,就返回那个结果,无论成功失败static race(promises) {return new MyPromise((resolve, reject) => {promises.forEach(promise => {if (promise instanceof MyPromise) {promise.then(res => {resolve(res);},err => {reject(err);});} else {resolve(promise);}});});}
10. allSettled
接收一个Promise数组,数组中如有非Promise项,则此项当做成功
把每一个Promise的结果,集合成数组,返回
static allSettled(promises) {return new Promise((resolve, reject) => {const res = [];let count = 0;const addData = (status, value, i) => {res[i] = {status,value,};count++;if (count === promises.length) {resolve(res);}};promises.forEach((promise, i) => {if (promise instanceof MyPromise) {promise.then(res => {addData("fulfilled", res, i);},err => {addData("rejected", err, i);});} else {addData("fulfilled", promise, i);}});});}
11. any
any 就是 all 的反过来
接收一个
Promise数组,数组中如有非Promise项,则此项当做成功- 如果有一个
Promise成功,则返回这个成功结果 - 如果所有
Promise都失败,则报错static any(promises) {return new Promise((resolve, reject) => {let count = 0;promises.forEach(promise => {promise.then(val => {resolve(val);},err => {count++;if (count === promises.length) {reject(new AggregateError("All promises were rejected"));}});});});}
