最详细的Promise相关源码实现

本文详细解析了Promise的源码实现,包括整体分析、初版实现、支持异步和链式调用、catch方法、Promise.resolve()、Promise.reject()、Promise.all()以及Promise.race()。文章通过逐步完善代码,解释了Promise的状态转换、异步处理、链式调用和值传透等功能,旨在帮助读者深入理解Promise的工作机制。
摘要由CSDN通过智能技术生成

写这篇文章的目的是解剖Promise源码,起因也是最近秋招被问到了让手写Promise,另外在网上看到的Promise源码或多或少有些小问题,也就是没有完全遵循Promise/A+规范。

代码会完全使用ES6语法,主要分以下几个模块:

  • 整体分析(为代码书写铺路)
  • 实现初版(构造函数大致功能亿完善)
  • 支持异步和链式调用(完善then方法)
  • 实现catch方法
  • 实现Promise.resolve()
  • 实现Promise.reject()
  • 实现Promise.all()
  • 实现Promise.race()

一、整体分析

所谓Promise就是一个容器,有三个状态:PENDING(进行中)、FULFILLED(成功)、REJECTED(失败),里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果,有两大特点:

  • 容器状态不受外界影响
  • 一旦状态改变就不会再变,任何时候都可以得到这个结果

来看下Promise的用法:

new Promise((resolve, reject) => {
  // ...
  // 成功则执行resolve,否则指定reject
}).then(
  res => {
    // resolve对应触发函数的执行
  },
  err => {
    // reject对应触发函数的执行
  }
).then(
  // 支持链式调用
  res => {
  
  }
).catch(
  err => console.log(err)
)
Promise.resolve();
Promise.reject();
Promise.all([promise1, promise2, ...]).then();
Promise.race([promise1, promise2, ...]).then();

通过用法不难分析出:

  • Promise构造函数接受一个函数参数exector,exector接受resolvereject两个函数并立即执行,通过resolve/reject改变状态
  • 状态改变后,触发原型链上的then、catch方法
  • Promise类拥有静态方法resolve、reject、all、race

那么可以写出大致结构代码:

class Promise {
   
  constructor(exector) {
   
    const resolve = () => {
   

    }
    const reject = () => {
   

    }
    exector(resolve, reject);
  }
  then() {
   

  }
  catch() {
   

  }
  static resolve() {
   

  }
  static reject() {
   

  }
  static all() {
   

  }
  static race() {
   
    
  }
}

之后在此基础上补充代码。

二、实现初版

首先引入三种状态,完善resolvereject函数,最后在构造函数内执行exector(resolve, reject)

// 定义三种状态
const PENDING = 'PENDING';      // 进行中
const FULFILLED = 'FULFILLED';  // 已成功
const REJECTED = 'REJECTED';    // 已失败

class Promise {
   
  constructor(exector) {
   
    // 初始化状态
    this.status = PENDING;
    // 将成功、失败结果放在this上,便于then、catch访问
    this.value = undefined;
    this.reason = undefined;

    const resolve = value => {
   
      // 只有进行中状态才能更改状态
      if (this.status === PENDING) {
   
        this.status = FULFILLED;
        this.value = value;
      }
    }
    const reject = reason => {
   
      // 只有进行中状态才能更改状态
      if (this.status === PENDING) {
   
        this.status = REJECTED;
        this.reason = reason;
      }
    }
    // 立即执行exector
    // 把内部的resolve和reject传入executor,用户可调用resolve和reject
    exector(resolve, reject);
  }
}

注意:exector(resolve, reject);执行可能会报错,所以需要使用try包括一下,有报错reject抛出去。

constructor(exector) {
   
  // 初始化状态
  this.status = PENDING;
  // 将成功、失败结果放在this上,便于then、catch访问
  this.value = undefined;
  this.reason = undefined;

  const resolve = value => {
   
    if (this.status === PENDING) {
   
      // 只有进行中状态才能更改状态
      this.status = FULFILLED;
      this.value = value;
    }
  }
  const reject = reason => {
   
    if (this.status === PENDING) {
   
      // 只有进行中状态才能更改状态
      this.status = REJECTED;
      this.reason = reason;
    }
  }
  // 修改代码
  try {
   
    // 立即执行executor
    // 把内部的resolve和reject传入executor,用户可调用resolve和reject
    exector(resolve, reject);
  } catch(e) {
   
    // executor执行出错,将错误内容reject抛出去
    reject(e);
  }
}

此时可以使用then进行捕获了,then接收两个函数,分别对应FULFILLEDREJECTED状态:

new Promise().then(
  res => {},
  err => {},
)

注意:thencatch是微任务,这里使用setTimeout模拟:

then(onFulfilled, onRejected) {
   
  // then是微任务,这里用setTimeout模拟
  setTimeout(() => {
   
    if (this.status === FULFILLED) {
   
      // FULFILLED状态下才执行
      onFulfilled(this.value);
    } else if (this.status === REJECTED) {
   
      // REJECTED状态下才执行
      onRejected(this.reason);
    }
  })
}

OK,初版已经完成:

// 定义三种状态
const PENDING = 'PENDING';      // 进行中
const FULFILLED = 'FULFILLED';  // 已成功
const REJECTED = 'REJECTED';    // 已失败

class Promise {
   
  constructor(exector) {
   
    // 初始化状态
    this.status = PENDING;
    // 将成功、失败结果放在this上,便于then、catch访问
    this.value = undefined;
    this.reason = undefined;

    const resolve = value => {
   
      if (this.status === PENDING) {
   
        // 只有进行中状态才能更改状态
        this.status = FULFILLED;
        this.value = value;
      }
    }
    const reject = reason => {
   
      if (this.status === PENDING) {
   
        // 只有进行中状态才能更改状态
        this.status = REJECTED;
        this.reason = reason;
      }
    }
    try {
   
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值