实现一个promise

45 阅读3分钟

promise是为了解决回调地狱所加入的语法,虽然他也存在部分问题 1.延时问题2.promise一旦创建,无法取消3.pending状态的时候,无法得知进展到哪一步(比如接口超时,可以借助race方法)4.promise会吞掉内部抛出的错误,不会反映到外部。如果最后一个then方法里出现错误,无法发现。(可以采取hack形式,在promise构造函数中判断onRejectedCb的数组长度,如果为0,就是没有注册回调,这个时候就抛出错误,某些库实现done方法,它不会返回一个promise对象,且在done()中未经处理的异常不会被promise实例所捕获)5.then方法每次调用都会创建一个新的promise对象,一定程度上造成了内存的浪费 ​ 我们先看看他的平常用法。

const promise = new Promise((resolve,  reject) => {
  if(true) {
    resolve('success')
  } else {
    reject('error') 
  }
})
 promise.then(value => {
   console.log(value)
 }, reason => {
   console.log(reason)
 }).then(value=> {
   console.log('value ' + value)
 }, error => {
   console.log('error ' + error) 
 })

链式操作 先写一个promise方法

class myPormise {
  // 这里的executor是我们传入的一个函数, 这个函数需要立即执行
  constructor(executor) {
    this.value = null

    // 这里有可能执行时报错,我们需要把所有的错误都交给reject处理 
    try {
      // 我们需要传入两个函数进去,因为会因为调用位置的变化,所以我们需要绑定一下this
      executor(this.resolve.bind(this), this.reject.bind(this)) 
    } catch(e) {
      this.reject(e) 
    }
  }

  resolve(value) {
    this.value = value 
  }

  reject(reason) {
    this.value = reason
  }
}

这个是终极版,有回调,有参数。

/*
手写一个promise
*/

function normalUse(Pro) {
  const Con = Pro || Promise;
  const promise = new Con((resolve, reject) => {
    const num = Math.random() * 10;
    if (num > 5) {
      resolve(num);
    } else {
      reject(num);
    }
  });
  promise
    .then(
      (value) => {
        console.log("success", value);
      },
      (reason) => {
        console.log("fail", reason);
      }
    )
    .then(
      (value) => {
        console.log("value " + value);
      },
      (error) => {
        console.log("error " + error);
      }
    );
}

const PENDING = "pending";
const FULLFILLED = "fullfilled";
const REJECT = "reject";

class MyPromise {
  constructor(executor) {
    // 执行函数,执行函数可以使用resolve reject
    this.executor = executor;
  }
  then(onFulfilled, onRejected) {
    this.onFulfilled = onFulfilled;
    this.onRejected = onRejected;
  }
}
var index = 2;
// 复杂的,全面的promise
class AllPromise {
  constructor(callback, name) {
    this.name = name; // 加一个promiseName
    this.callback = callback;
    this.value = undefined;
    this.error = undefined;
    this.status = PENDING;
    this.onResCallbacks = [];
    this.onFailCallbacks = [];
    const resolve = (value) => {
      console.log("r promiseName", this.name, this.onResCallbacks.length);
      this.status = FULLFILLED;
      this.value = value;
      this.onResCallbacks.forEach((cb) => cb(value));
    };
    const reject = (erorr) => {
      console.log("e promiseName", this.name);
      if (this.status === PENDING) {
        this.status = REJECT;
        this.error = erorr;
        this.onFailCallbacks.forEach((cb) => cb(erorr));
      }
    };
    callback(resolve, reject); // 扔出两个函数(失败和成功,供调用)
  }
  then(onFulfilled, onRejected) {
    // then的第二个参数(onRejected)可以当做catch,如果执行了的话,那么后面跟着的catch就不会执行
    // 当然,then中任何报错都会走到后面的catch中。
    console.log("onFulfilled", onFulfilled, this.name);
    onFulfilled =
      typeof onFulfilled === "function" ? onFulfilled : (value) => value;
    onRejected =
      typeof onRejected === "function" ? onRejected : (error) => error;
    const pr1 = new AllPromise((resolve, reject) => {
      if (this.status === FULLFILLED) {
        console.log("fullfilled", this.name);
        try {
          const x = onFulfilled(this.value);
          resolve(x);
        } catch (error) {
          reject(error);
        }
      } else if (this.status === REJECT) {
        console.log("reject", this.name);
        try {
          const x = onRejected(this.error);
          resolve(x);
        } catch (error) {
          reject(error);
        }
      } else if (this.status === PENDING) {
        console.log("PENDING,堆栈", this.name);
        // 这里就是堆栈,把链式操作堆在后面。
        // promise值给下一个promise(then),子的执行函数往父上堆。
        this.onResCallbacks.push(() => {
          if (this.status === FULLFILLED) {
            try {
              const x = onFulfilled(this.value);
              console.log("执行结果", x, this.name);
              resolve(x);
            } catch (error) {
              reject(error);
            }
          }
        });
        // 需要注意的是,这里的fail也要对入栈。yehji
        this.onFailCallbacks.push(() => {
          try {
            const x = onRejected(this.value);
            resolve(x);
          } catch (error) {
            reject(error);
          }
        });
      } else {
        this.onResCallbacks = [];
        this.onFailCallbacks = [];
      }
    }, `promise${index++}`);
    return pr1;
  }
  catch(onRejected) {
    return this.then(null, onRejected);
  }
}

const promise = new AllPromise((resolve, reject) => {
  setTimeout(() => {
    console.log("timeout");
    resolve("成功");
  }, 1000);
}, "promise1");
promise
  .then(1111111)
  .then((value) => {
    console.log("2");
    // return "第一次"
    setTimeout(() => {
      console.log("55555");
      return "第一次";
    }, 1000);
  })
  .then((value) => {
    console.log("3");
    return new AllPromise((resolve, reject) => {
      setTimeout(() => {
        resolve("第二次处理结果");
      }, 1000);
    }, "end Promise");
  })
  .then((value) => {
    console.log(value);
    throw new Error("抛出异常");
  })
  .catch((error) => {
    console.log(error);
  });

每次then都是一个promise。 ​ 参考:简单实现一个promise 手动实现promise