拿来吧你,Promise构造函数

260 阅读3分钟

最近看到一段语句,分享给在看的你:小时候,哭是解决问题的法宝,长大后,笑是面对生活的武器。 使用方式:

let promise1 = new Promise((resolve, reject) => {
    resolve(1)
    });
promise1.then(res => console.log(res))

分析: new Promise(xxx)返回一个对象promise1,promise1.then(()=>{}, ()=>{}),当前方的a函数中调用了resolve(promise1的结果),那么then中的函数就会被执行。 resolve怎么来的,势必是原型上的,then方法中的函数参数,势必是被加入到实例的属性上了,且加入到前面实例的方法中还存储着改变当前then返回的这个promise实例的能力;

/*
 * @Author: zhangbuzhou
 * @Date: 2021-07-24 21:42:47
 * @LastEditTime: 2021-07-24 22:01:47
 * @LastEditors: Please set LastEditors
 * @Description: In User Settings Edit
 * @FilePath: \myvue-project-runtime-only\src\utils\MyPromise.js
 */
function MyPromise(executor) {
  this.value = "";
  this.status = "pending"; // resolved、rejected
  this.onResolvedCallbackArr = []; // 实例promise1可以调用多次then方法
  this.onRejectedCallbackArr = [];
  // 异步结束:成功,改变实例状态,调用then中回调
  const resolve = (response) => {
    setTimeout(() => {
      // promise实例的状态改变后,就不可再改变,这里只做了简单限制,
      // 我觉得还可以使用object.defineproperty将status属性改为无法使用赋值改变
      if (this.status === "pending") {
        this.value = response;
        this.status = "resolved";
        // 如果实例后面调用了then方法,此时已经加入到fulfiledCallbackArr数组当中
        this.onResolvedCallbackArr.forEach((callback) => {
          callback(response);
        });
      }
    }, 0);
  };
  const reject = (error) => {
    setTimeout(() => {
      // 同resolve
      if (this.status === "pending") {
        this.value = error;
        this.status = "rejected";
        this.onRejectedCallbackArr.forEach((callback) => {
          callback(error);
        });
      }
    });
  };
  try {
    executor(resolve, reject);
  } catch (err) {
    reject(err);
  }
}


// 当promise实例 A 调用then方法,其实是将一个回调加入到这个promise实例 A 当中,
// 当这个实例 A 的异步结束后,也就是调用了resolve,改变状态的同时会调用then中写的回调函数
// 这个回调函数又可以调用then方法创建的实例 B 的resolve改变状态,改变状态的同时,还会调用B实例的then中回调
// 这样就实现了链式回调
MyPromise.prototype.then = function(resolveFn, rejectFn) {
  return new MyPromise((resolve, reject) => {
    // 防止then中参数不是或者没传函数,保证即使then中没传参数,也可以继续链式调用
    typeof resolveFn === 'function' ? null : resolveFn = res => res;
    typeof rejectFn === 'function' ? null : rejectFn = err => err;
    this.fulfiledCallbackArr.push(() => {
      try {
        let result = resolveFn(this.value);
        // 如果then中函数返回的是一个promise实例,那么此promise实例的状态依据这个返回值result的状态
        // 这里是重点,理解then的作用,就可理解result.then(resolve)是为何了
        result instanceof MyPromise ? result.then(resolve) : resolve(result);
      } catch (err) {
        reject(err);
      }
    });
    this.rejectedCallbackArr.push(() => {
      try {
        let result = rejectFn(this.value);
        result instanceof MyPromise ? result.then(resolve) : resolve(result);
      } catch (err) {
        reject(err);
      }
    });
  });
};
// 上面的then方法,在pending状态时,添加的监听函数能够在状态改变时得到响应,
// 当状态已经改变时,直接then会立即添加一个微任务,所以完整版的话还需要判断promise的状态

// 理解了上述,再实现promise的一些静态方法
MyPromise.all = function (promiseArr) {
  let len = promiseArr.length;
  let result = [];// 保存每个实例的结果
  return new MyPromise((resolve, reject) => {
    promiseArr.forEach(promiseObj => {
      promiseObj.then(res=> {
        len --;
        result.push(res);
        if(!len) {
          resolve(result);
        }
      })
    })
  })
}
MyPromise.resolve = function (value) {
  return value instanceof MyPromise
    ? new MyPromise((resolve, reject) => value.then(resolve, reject))
    : new Promise((resolve) => resolve(value));
};
MyPromise.reject = function (value) {
  return value instanceof MyPromise
    ? new MyPromise((resolve, reject) => value.then(resolve, reject))
    : new Promise((resolve, reject) => reject(value));
};