实现Promise

170 阅读4分钟

Promise

有三种状态,pending(进行中)、fulfilled(已成功)、rejected(已失败)

Promise的使用

new Promise((resolve, reject) => {
  // resolve & reject:是自己任意执行的,但是一般情况下,大家都约定成功执行resolve,失败执行reject
  // => excutor函数(执行函数)中可以不管控异步操作(但是不管控异步没什么意义)
  resolve(100)
}).then(result => {
  // resolve执行的时候会触发第一个回调函数执行
  console.log(1)
  return 1000; //=>会把这个值传递给下一个then中的方法,如果返回的是一个新的promise实例,则等到promise处理完成,把处理完成的结果传递给下一个then
},reason =>{
  // reject执行的时候会触发第二个回调函数执行
  console.log(2)
}).then(result =>{ //需要保证执行then方法返回的依然是promise实例,这样才可以实现链式调用
  // =>上一个then中管控的两个方法只要任何一个执行不报错,都会执行和这个then中的第一个方法,如果执行报错,会执行此then中的第二个回调函数
}).catch(reason =>{
  // catch就相当于then(null,reason =>{})
})
console.log(3)


// => 等待所有的promise都成功执行then,反之只要有一个失败就会执行catch
Promise.all([promise1,...]).then()

初始的Promise

class Promise {
  constructor(excutorCallback) {
    this.status = 'pending';  //默认状态
    this.value = 'undefined'; //结果
    this.fulfilledAry = []; //成功要做的方法
    this.rejectedAry = []; //失败要做的方法
    let resolveFn = result => {
      let timer = setTimeout(() => {  //设置定时器,将以下任务放进宏任务区,等待主栈任务完成
        clearTimeout(timer);
        if (this.status !== 'pending') return
        this.status = 'fulfilled';
        this.value = result;
        this.fulfilledAry.forEach(item => item(this.value))  //执行成功函数,并传递值
      }, 0)

    }
    let rejectFn = reason => {
      let timer = setTimeout(() => { //设置定时器,将以下任务放进宏任务区,等待主栈任务完成
        clearTimeout(timer);
        if (this.status !== 'pending') return
        this.status = 'rejected';
        this.value = reason;
        this.rejectedAry.forEach(item => item(this.value)) //执行失败函数,并传递值
      }, 0)

    }
    // 执行excutor (异常捕获) 如果excutorCallback函数执行发现异常,捕获异常,执行rejectFn函数
    try {
      excutorCallback(resolveFn, rejectFn)
    } catch (err) {
      // 有异常信息按照rejected状态处理
      rejectFn(err)
    }
  }
  then(fulfilledCallback, rejectedCallback) {   //then方法
    if (typeof fulfilledCallback === 'function') {  //检测是否是方法
      this.fulfilledAry.push(fulfilledCallback)
    }
    if (typeof rejectedCallback === 'function') {
      this.rejectedAry.push(rejectedCallback)
    }
  }
}

Promise链式调用原理

原生promise执行原理

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    Math.random() < 0.5 ? resolve(100) : reject(-100)
  }, 1000)

})
let p2 = p1.then(result => {
  return result + 100;
}, reason => {
  return reason - 100;
});

p2.then(result => {
  console.log(p1 === p2) //执行then返回的是一个新的promise实例
  console.log(result)
}, reason => {
  console.log(p1 === p2)
  console.log(reason)
})
console.log(3)

Promise.all用法

let p1 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(100)
  }, 50)
})
let p2 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(200)
  }, 10)
})
let p3 = new Promise((resolve, reject) => {
  setTimeout(() => {
    resolve(300)
  }, 80)
})

Promise.all([p1,p2,p3]).then(result => {
  // 所有的promise都成功执行,result中分别存储每一个实例返回的结果,而且和数组中的顺序是一样的
  console.log(result) //[ 100, 200, 300 ]
}).catch(reason => {
  // 只要有一个失败,就执行这个方法,失败后不再执行后面的操作
  console.log(reason)
})

完整版Promise

class Promise {
  constructor(excutorCallback) {
    this.status = 'pending';  //默认状态
    this.value = 'undefined'; //结果
    this.fulfilledAry = []; //成功要做的方法
    this.rejectedAry = []; //失败要做的方法
    let resolveFn = result => {
      let timer = setTimeout(() => {  //设置定时器,将以下任务放进宏任务区,等待主栈任务完成
        clearTimeout(timer);
        if (this.status !== 'pending') return
        this.status = 'fulfilled';
        this.value = result;
        this.fulfilledAry.forEach(item => item(this.value))  //执行成功函数,并传递值
      }, 0)

    }
    let rejectFn = reason => {
      let timer = setTimeout(() => { //设置定时器,将以下任务放进宏任务区,等待主栈任务完成
        clearTimeout(timer);
        if (this.status !== 'pending') return
        this.status = 'rejected';
        this.value = reason;
        this.rejectedAry.forEach(item => item(this.value)) //执行失败函数,并传递值
      }, 0)

    }
    // 执行excutor (异常捕获) 如果excutorCallback函数执行发现异常,捕获异常,执行rejectFn函数
    try {
      excutorCallback(resolveFn, rejectFn)
    } catch (err) {
      // 有异常信息按照rejected状态处理
      rejectFn(err)
    }
  }
  then(fulfilledCallback, rejectedCallback) {   //then方法
    // 如果成功函数没有传递,创建一个函数帮它传递
    typeof fulfilledCallback !== 'function' ? fulfilledCallback = result => result : null;
    // 如果失败函数没有传递,创建一个函数帮它承接错误,并且抛给下一个then的错误函数
    typeof rejectedCallback !== 'function' ? rejectedCallback = reason => {
      // 判断reason是否是一个异常,如果是异常,把异常的message抛出,如果不是异常,把原值抛出
      throw new Error(reason instanceof Error ? reason.message : reason)
    } : null;

    //每次执行then,返回一个新的promise实例
    return new Promise((resolve, reject) => {
      this.fulfilledAry.push(() => {  //=>在外层包一层匿名函数
        // 当这个函数执行的时候,如果发生异常,捕获异常,并用reject把异常抛出
        try {
          // 执行传递进来的函数,并把对应的值传给函数,获取函数的返回值
          let x = fulfilledCallback(this.value);
          // 如果函数的返回值是有个新的Promise函数,直接调用这个新Promise的then方法
          // 如果不是Promise函数,直接调用resolve方法,并且把值传递过去,抛给下一个then
          x instanceof Promise ? x.then(resolve, reject) : resolve(x);
        } catch (err) {
          reject(err);
        }
      })
      this.rejectedAry.push(() => {
        try {
          let x = rejectedCallback(this.value);;
          x instanceof Promise ? x.then(resolve, reject) : resolve(x);
        } catch (err) {
          reject(err);
        }
      })
    })
  }
  catch(rejectedCallback) {
    return this.then(null, rejectedCallback)
  }
  static all(promiseAry = []) { //=>私有属性 使用Promise.all()调用
    return new Promise((resolve, reject) => {
      // index:记录成功的数量
      // result:记录成功的结果
      let index = 0,
        result = [];
      for (let i = 0; i < promiseAry.length; i++) {
        // promiseAry[i] :每一个需要处理的Promise实例
        promiseAry[i].then(val => {
          index++;
          result[i] = val;  //索引需要和promiseAry对应上,保证结果的顺序和数组顺序一致
          if (index === promiseAry.length) {
            resolve(result)
          }
        },reject)    //失败就执行reject
      }
    })
  }
}
module.exports = Promise;