promise源码

111 阅读3分钟
const FULFILLED = "FULFILLED";
const REJECTED = "REJECTED";
// 所有的promise 都要遵循这个规范 这样就可以保证不同人写的promise可以混用
// 核心就在这个resolvePromise方法中
function resolvePromise(x, promise2, resolve, reject) {
  // x 决定promise2 的状态 走成功还是失败
  if (promise2 === x) {
    return reject(new TypeError("循环引用"));
  }
  // 判断x 是不是一个promise 先保证x 得是一个对象或者函数,如果不是对象或者函数那么x 一定不是promise
  if ((typeof x === "object" && x !== null) || typeof x === "function") {
    let called;
    // 我需要看 这个x 上有没有then方法 有then方法才说明他是一个promise
    try {
      let then = x.then; // x可能是别人写的promise 那么取then有风险,
      if (typeof then === "function") {
        then.call(x,(y) => {
            // x.then((y)=>{},r=>{}) 取then就会有风险
            if (called) return;
            called = true;
            resolvePromise(y, promise2, resolve, reject); // 递归解析直到我们的y的值是一个普通值
          },
          (r) => {
            if (called) return;
            called = true;
            reject(r);
          }
        );
      } else {
        //  没有then方法的都执行这里
        resolve(x); // 只是一个对象而已 就是一个普通值
      }
    } catch (e) {
      if (called) return;
      called = true;
      reject(e);
    }
  } else {
    // x 就是一个普通的值,直接把x 传递给promise2的成功即可
    resolve(x);
  }
}
class Promise {
  constructor(executor) {
    this.value = undefined;
    this.reason = undefined;
    this.status = PENDING;
    this.onResvoledCallbacks = [];
    this.onRejectedCallbacks = [];
    const resolve = (value) => {
      // 如何判断是不是一个promise 主要看有没有then方法
      if (value instanceof Promise) {
        return value.then(resolve, reject);
      }
      if (this.status === PENDING) {
        this.status = FULFILLED;
        this.value = value;
        this.onResvoledCallbacks.forEach((fn) => fn());
      }
    };
    const reject = (reason) => {
      if (this.status === PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        this.onRejectedCallbacks.forEach((fn) => fn());
      }
    };
    try {
      executor(resolve, reject);
    } catch (e) {
      reject(e);
    }
  }
  then(onFulfilled, onRejected) {
    // 有可能这个 onFulfilled, onRejected 是可选的
    onFulfilled =
      typeof onFulfilled === "function"
        ? onFulfilled
        : function (data) {
          return data;
        };
    onRejected =
      typeof onRejected === "function"
        ? onRejected
        : (err) => {
          throw err;
        };
    let promise2 = new Promise((resolve, reject) => {
      if (this.status === FULFILLED) {
        setTimeout(() => {
          try {
            let x = onFulfilled(this.value);
            resolvePromise(x, promise2, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      if (this.status === REJECTED) {
        setTimeout(() => {
          try {
            let x = onRejected(this.reason);
            resolvePromise(x, promise2, resolve, reject);
          } catch (e) {
            reject(e);
          }
        }, 0);
      }
      if (this.status === PENDING) {
        this.onResvoledCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onFulfilled(this.value);
              resolvePromise(x, promise2, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
        this.onRejectedCallbacks.push(() => {
          setTimeout(() => {
            try {
              let x = onRejected(this.reason);
              resolvePromise(x, promise2, resolve, reject);
            } catch (e) {
              reject(e);
            }
          }, 0);
        });
      }
    });
    return promise2;
  }
  catch(errCallback) {
    return this.then(null, errCallback);
  }
  static reject(reason) {
    return new Promise((resolve, reject) => {
      reject(reason);
    });
  }
  static resolve(value) {
    return new Promise((resolve, reject) => {
      resolve(value);
    });
  }
  static all(values) {
    return new Promise((resolve, reject) => {
      let times = 0;
      function processMap(key, value) {
        arr[key] = value;
        if (++times === values.length) {
          resolve(arr);
        }
      }
      const arr = [];
      for (let i = 0; i < values.length; i++) {
        let val = values[i]; // 可能是promise 也有可能是普通值
        let then = val && val.then;
        if (typeof then === "function") {
          then.call(
            val,
            (data) => {
              // 获取成功的结果
              processMap(i, data);
            },
            reject
          );
        } else {
          processMap(i, val);
        }
      }
    });
  }
  finally(cb) {
    return this.then(
      (y) => {
        return Promise.resolve(cb()).then(() => y);
      },
      (r) => {
        return Promise.resolve(cb()).then(() => {
          throw r;
        });
      }
    );
  }
}
reject(new Promise((resolve, reject) => {
          setTimeout(()=>{
          resolve('123')
      })
}));
其实走到then的第二个回调函数中 , 然后拿到回调中的值其实是一个 Promise
resolve(new Promise((resolve, reject) => {
          setTimeout(()=>{
          resolve('123')
      })
}));
这个在then的第1个回调函数中,拿到123
// const Promise = require("./promise");
Promise.race = function (values) {
  return new Promise((resolve, reject) => {
    for (let i = 0; i < values.length; i++) {
      let p = values[i]; //  p可能是promise 也可能是普通值
      // 无论谁先成功就成功 谁先失败就失败
      // 原生的promise, 如果你里面放的是一个promise 会进行优化, 不会在进行包装了   1次then
      // 我们自己写的promise 多了一个条件 如果当前resolve里面放的是promise,我会调用这个promise.then  2次then
      Promise.resolve(p).then(resolve, reject);
    } 
  });
};
// 赛跑   面试的时候 会考察如何实现超时处理  有一个成功或者失败就结束了

Promise.race([
  new Promise((resolve, reject) => {
    // 这个玩意没有所谓的异步任务
    reject(100);
  }),
  200,
])
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err, "catch");
  });

// ------------race使用场景---------------

// 超时 模拟取消操作 promise 不能随便取消
// 延迟对象 dfd = {promise,resolve,reject}
// let abort = null;
let p = new Promise((resolve, reject) => {
  //   abort = reject;
  setTimeout(() => {
    resolve("ok");
  }, 3000);
});
function withAbort(p) {
  // Promise.race([p,'我的内部的promise '])
  let abort = null;
  let myErrorPromise = new Promise((resolve, reject) => {
    abort = reject;
  });
  let returnPromise = Promise.race([p, myErrorPromise]); // 有任何一个promise失败了就失败
  returnPromise.abort = abort;
  return returnPromise;
}
let promise2 = withAbort(p);
setTimeout(() => {
  promise2.abort("超时"); // 抢先调用了promise的失败方法 , 自己控制这个promise走向失败
}, 5000);
promise2
  .then((data) => {
    console.log(data);
  })
  .catch((err) => {
    console.log(err, "fail");
  });
Promise.resolve().then(() => {
    console.log('then1');
     Promise.resolve().then(() => {
        console.log('then1-1');
        // 调用x.then
        //  x.then()
        // 在ECMASCRIPT中 如果then中的回调返回了一个promise ,那么会自动再次产生一个then
        return Promise.resolve();  //then中的回调返回一个promise 会等待这个promise完成 Promise.resolve().then().then()
    }).then(() => {
        console.log('then1-2')
    })
})
    .then(() => {
        console.log('then2');
        return undefined
    })
    .then(() => {
        console.log('then3');
    })
    .then(() => {
        console.log('then4');
    })
    .then(() => {
        console.log('then5');
    })