手写Promise简易版

150 阅读1分钟

简易版代码

const PENDING = 'PENDING';
const FULFILLED = 'FULFILLED';
const REJECTED = 'REJECTED';

class ZPromise {
  constructor(executor) {
    this.status = PENDING;
    this.value = undefined;
    this.reason = undefined;
    // 存放成功的回调
    this.onResolvedCallbacks = [];
    // 存放失败的回调
    this.onRejectedCallbacks= [];

    let resolve = (value) => {
      if(this.status ===  PENDING) {
        this.status = FULFILLED;
        this.value = value;
        // 依次将对应的函数执行
        this.onResolvedCallbacks.forEach(fn=>fn());
      }
    } 

    let reject = (reason) => {
      if(this.status ===  PENDING) {
        this.status = REJECTED;
        this.reason = reason;
        // 依次将对应的函数执行
        this.onRejectedCallbacks.forEach(fn=>fn());
      }
    }

    try {
      executor(resolve,reject)
    } catch (error) {
      reject(error)
    }
  }

  then(onFulfilled, onRejected) {
    if (this.status === FULFILLED) {
      onFulfilled(this.value)
    }

    if (this.status === REJECTED) {
      onRejected(this.reason)
    }

    if (this.status === PENDING) {
      // 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行
      this.onResolvedCallbacks.push(() => {
        onFulfilled(this.value)
      });

      // 如果promise的状态是 pending,需要将 onFulfilled 和 onRejected 函数存放起来,等待状态确定后,再依次将对应的函数执行
      this.onRejectedCallbacks.push(()=> {
        onRejected(this.reason);
      })
    }
  }
}

总结Promise特点

  1. Promise里的函数是立即执行的
  2. resolve()将pending=>fulfilled,reject()会将pending=>rejected,不可逆
  3. then方法返回的是一个新的Promise对象
  4. then方法相当于是添加到一个微任务队列里,resolve之后才会执行
  5. reject()会立即抛错,被catch()之后,返回一个新的fulfilled状态的Promise对象
  6. 状态可以一直是pending,如果没有resolve或者reject的话
  7. then(fulfilledFn,rejectedFn),resolve会执行fulfilledFn,reject会执行rejectedFn
  8. Promise是没有中断操作的

fetch基于Promise实现,所以也没有中断方法,axios基于ajaxs实现了中断

基于Promise.race()实现promise中断

function wrap(promise){
  let about;
  let rejectPromise=new Promise((resolve,reject)=>{
    about=reject
  })
  let pr=Promise.race([promise,rejectPromise])
  // promise对象不能使用展开符{...pr}
  pr.about=about
  return pr
}

进阶

写一个符合 Promises/A+ 规范并可配合 ES7 async/await 使用的 Promise

最简实现Promise,支持异步链式调用(20行)

面试官:“你能手写一个 Promise 吗”