promise相关手写代码题

320 阅读4分钟

1.实现promise方法

promise功能点:

  1. 三个状态 pending,fulfilled,rejected
  2. 自动执行
class MyPromise {
  constructor(executor) {
    this.state = "pending"; //默认的状态,进行中
    this.value = null; //成功后携带的值
    this.reason = null; //失败后携带的原因
    this.onFulfilledCallbacks = [];
    this.onRejectedCallbacks = [];
    const resolve = (value) => {
      if (this.state === "pending") {
        this.state = "fulfilled";
        this.value = value;
        this.onFulfilledCallbacks.forEach((fn) => fn(this.value));
      }
    };
    const reject = (reason) => {
      if (this.state === "pending") {
        this.state = "rejected";
        this.reason = reason;
        this.onRejectedCallbacks.forEach((fn) => fn(this.reason));
      }
    };
    try {
      executor(resolve, reject); //构造器执行
      //这里可以考虑一个特殊情况
      //如果res是promise则等待res状态结束再执行resolve或者reject
      // executor((res)=>{
      //   resolvePromise(res, resolve, reject);
      // },reject)
    } catch (err) {
      reject(err);
    }
  }
  //then函数根据state来进行后续的回调函数操作
  //考虑then的链式调用,返回一个promise
  //只考虑onFulfilled是返回一个值的话
  // then(onFulfilled, onRejected) {
  //   if (this.state === "fulfilled") {
  //     return new MyPromise((resolve, reject) => {
  //       onFulfilled(this.value);
  //     });
  //   }
  //   if (this.state === "rejected") {
  //     return new MyPromise((resolve, reject) => {
  //       onRejected(this.reason);
  //     });
  //   }
  //   if (this.state === "pending") {
  //     return new MyPromise((resolve, reject) => {
  //       this.onFulfilledCallbacks.push(onFulfilled);
  //       this.onRejectedCallbacks.push(onRejected);
  //     });
  //   }
  // }
  //考虑onFulfilled也可能是一个promise,则需要在onFulfilled执行完成之后再进行resolve,reject
  then(onFulfilled, onRejected) {
    if (this.state === "fulfilled") {
      return new Promise((resolve, reject) => {
        try {
          let f = onFulfilled(this.value);
          if (f instanceof Promise) {
            f.then(resolve, reject);
          } else {
            resolve(f);
          }
        } catch (err) {
          reject(err);
        }
      });
    }
    if (this.state === "rejected") {
      return new Promise((resolve, reject) => {
        try {
          let j = onRejected(this.reason);
          if (j instanceof Promise) {
            j.then(resolve, reject);
          } else {
            resolve(j);
          }
        } catch (err) {
          reject(err);
        }
      });
    }
    if (this.state === "pending") {
      return new Promise((resolve, reject) => {
        this.onFulfilledCallbacks.push(() => {
          let f = onFulfilled(this.value);
          if (f instanceof Promise) {
            f.then(resolve, reject);
          } else {
            resolve(f);
          }
        });
        this.onRejectedCallbacks.push(() => {
          let j = onRejected(this.reason);
          if (j instanceof Promise) {
            j.then(resolve, reject);
          } else {
            resolve(j);
          }
        });
      });
    }
  }
}
//这个方法主要判断如果p是promise,那就在p的promise pending状态结束后执行resolve和reject方法
function resolvePromise(p, resolve, reject) {
  try {
    if (p instanceof MyPromise) {
      p.then((res) => {
        resolvePromise(res, resolve, reject);
      }, reject);
    } else {
      resolve(p);
    }
  } catch (err) {
    reject(err);
  }
}
//举个例子
console.log(1);
let p = new MyPromise((resolve, reject) => {
  setTimeout(() => {
    resolve(3);
    console.log(2);
  }, 2000);
}).then((value) => console.log(value));
console.log(4);
// 1 4 3 2

2.实现promise.resolve

Promsie.resolve(value) 可以将任何值转成值为 value 状态是 fulfilled 的 Promise,但如果传入的值本身是 Promise 则会原样返回它。

 Promise.resolve = function(value) {
    // 如果是 Promsie,则直接输出它
    if(value instanceof Promise){
        return value
    }
    return new Promise(resolve => resolve(value))
}

3.实现Promise.reject

和 Promise.resolve() 类似,Promise.reject() 会实例化一个 rejected 状态的 Promise。但与 Promise.resolve() 不同的是,如果给 Promise.reject() 传递一个 Promise 对象,则这个对象会成为新 Promise 的值。

Promise.reject = function(reason) {
    return new Promise((resolve, reject) => reject(reason))
}

4.实现Promise.all

  • 传入的所有 Promsie 都是 fulfilled,则返回由他们的值组成的,状态为 fulfilled 的新 Promise;
  • 只要有一个 Promise 是 rejected,则返回 rejected 状态的新 Promsie,且它的值是第一个 rejected 的 Promise 的值;
  • 只要有一个 Promise 是 pending,则返回一个 pending 状态的新 Promise; 总结:所有请求都成功后返回成功,任意一个失败返回失败 使用场景:
    1.前端发起多个请求并根据请求顺序获取和使用数据;
    2.合并多个请求结果并处理错误
var myPromiseAll = (arr) => {
  let res = [];
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arr.length; i++) {
      //Promise.resolve()方法将所有对象转换为promise对象
      Promise.resolve(arr[i]).then(
        (value) => {
          res[i] = value;
          // 当所有函数都正确执行了,resolve输出所有返回结果。
          if (res.length === arr.length) {
            return resolve(res);
          }
        },
        (err) => {
          return reject(err);
        }
      );
    }
  });
};
let p1 = Promise.resolve(3);
let p2 = 1337;
let p3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, "foo");
});
myPromiseAll([p1, p2, p3]).then((values) => {
  console.log(values); // [3, 1337, "foo"]
});

5.实现Promise.race

Promise.race 会返回一个由所有可迭代实例中第一个 fulfilled 或 rejected 的实例包装后的新实例。 总结:返回第一个,不论成功还是失败 使用场景:请求超时提醒。

var myPromiseRace = (arr) => {
  let isFrist = true;
  return new Promise((resolve, reject) => {
    for (let i = 0; i < arr.length; i++) {
      Promise.resolve(arr[i]).then(
        (value) => {
          if (isFrist) {
            isFrist = false;
            return resolve(arr[i]);
          }
        },
        (err) => {
          if (isFrist) {
            isFrist = false;
            return reject(err);
          }
        }
      );
    }
    Promise.resolve();
  });
};

6.实现Promise.any

  • 空数组或者所有 Promise 都是 rejected,则返回状态是 rejected 的新 Promsie,且值为 AggregateError 的错误;
  • 只要有一个是 fulfilled 状态的,则返回第一个是 fulfilled 的新实例;
  • 其他情况都会返回一个 pending 的新实例; 总结:返回第一个成功的,全部错误则返回错误 使用场景:从最快的服务器检索资源,如果存在多台服务器,从最快的一台服务器获取资源。
var myPromiseAny = function(promiseArr) {
    let index = 0
    return new Promise((resolve, reject) => {
        if (promiseArr.length === 0) return 
        promiseArr.forEach((p, i) => {
            Promise.resolve(p).then(val => {
                resolve(val)
                
            }, err => {
                index++
                if (index === promiseArr.length) {
                  reject(new AggregateError('All promises were rejected'))
                }
            })
        })
    })
}

7.实现Promise.allSettled

Promise.allSettled 的规则是这样:

  • 所有 Promise 的状态都变化了,那么新返回一个状态是 fulfilled 的 Promise,且它的值是一个数组,数组的每项由所有 Promise 的值和状态组成的对象;
  • 如果有一个是 pending 的 Promise,则返回一个状态是 pending 的新实例;
Promise.allSettled = function(promiseArr) {
    let result = []
        
    return new Promise((resolve, reject) => {
        promiseArr.forEach((p, i) => {
            Promise.resolve(p).then(val => {
                result.push({
                    status: 'fulfilled',
                    value: val
                })
                if (result.length === promiseArr.length) {
                    resolve(result) 
                }
            }, err => {
                result.push({
                    status: 'rejected',
                    reason: err
                })
                if (result.length === promiseArr.length) {
                    resolve(result) 
                }
            })
        })  
    })   
}

8.实现Promise.finally

不管成功还是失败,都会走到finally中,并且finally之后,还可以继续then。并且会将值原封不动的传递给后面的then

Promise.prototype.finally = function (callback) {
    return this.then((value) => {
        return Promise.resolve(callback()).then(() => {
            return value;
        });
    }, (err) => {
        return Promise.resolve(callback()).then(() => {
            throw err;
        });
    });
}