【手写 Promise 源码】第三篇 - 实现一个简版 Promise

413 阅读4分钟

一,前言

上一篇,结合示例介绍了 Promise 相关功能与特性分析,包含以下内容:

  • Promise 基础特性;
  • Promise 实例 API(原型方法);
  • Promise 静态 API(类方法);
  • Promise 在不同场景下的特性分析;

本篇,根据之前对 Promise 的分析和了解,实现一个简版 Promise;


二,Promise 的实现思路

基于前面对 Promise 使用上的了解和分析,Promise 有以下几个关键特征:

  • Promise 是一个类;
  • 构造函数接收的参数是一个 excutor 函数;
  • 这个函数的参数是 resolve 和 reject 两个内部函数;
  • 构建 resolve 和 reject 并传入 excutor,并使之立即执行;
  • Promise 类有三种状态,默认为等待态;
  • 在 resolve 和 reject 中修改 status 状态;
  • Promise 类中包含 then 和 catch 等方法;

那么,一个 Promise 的结构如下:

class Promise () {
  constructor (fun) {
    this.status = 'pending'; // status:pending、fulfilled、rejected
    fun(this.resolve, this.reject); // 主体函数将会被立即执行
  }
  resolve() {}
  reject() {}
  then() {}
  catch() {}
}

三,Promise A+ 规范(简版)

上边的代码是根据理解“猜测”出来的,比较严谨的应该根据 Promise A+ 规范进行实现;

备注:本篇仅介绍 Promise A+ 规范中的基础部分,用于支撑实现简版 Promise;

1,技术点

image.png

  • 1.1 promise 是一个对象或函数,要有一个 then 方法,而且 then 方法需要符合规范;
  • 1.2 thenable 是一个对象或函数
  • 1.3 value 是一个合法的 js 值,可以是 undefined,一个 thenable 对象,或者是一个 promise 对象;
  • 1.4 异常可以使用 throw 代码块抛出
  • 1.5 reson 是一个值,它告诉我们 promise 为什么被拒绝了

简单分析:

  • promise有多种实现方式,可以是对象也可以是函数;符合标准即可;
  • 由于 promise 实例可以.then,所以我们认为 promise 实例是一个 thenable 对象;
  • 调用 reslove() 可以传值,不传就是 undefined,也可以传入 promise 或 thenable;

2,必要的

2.1 promise 状态

image.png

promise 有三个状态:pending等待态, fulfilled成功态 和 rejected失败态.

  • 2.1.1 当 promise 为 pending等待态 时,可以转换为fulfilled成功态 或 rejected失败态.
  • 2.1.2 当 promise 为 fulfilled成功态 时
    • 2.1.2.1 不能被转化为其他状态
    • 2.1.2.2 必须有一个值,且不能被改变
  • 2.1.3 当 promise 为 rejected失败态 时
    • 2.1.3.1 不能被转化为其他状态
    • 2.1.3.2 必须有一个原因,且不能被改变

2.2 then 是一个方法

image.png

一个 promise 必须有一个 then 方法,而且能够访问成功或失败的值; 一个 promise 能够接收两个参数,onFulfilled 和 onRejected;

。。。后面的内容暂时略过。。。

备注:了解至以上内容,足以支撑实现简版 Promise;

那么,可以基于以下 5 点,实现一个简版的 Promise:

1,promise 是一个类;
2, 使用 promise 时,传入 executor 执行器,并被立即执行;
3,executor 参数是两个函数,用于描述 promise 实例的状态;
resolve 表示成功,可以传入一个 value;
reject 表示失败,可以传入一个 reason;
4,每个 Promise 实例都有一个 then 方法;
5,promise 一旦状态发生后,不能再更改,
promise 有三种状态:成功态,失败态,等待态(默认)

四、实现简版 Promise

// 声明 promise 三种状态
const PENDING = 'PENDING';     // 等待态
const DULFILLED = 'DULFILLED'; // 成功态
const REJECTED = 'REJECTED';   // 失败态

class Promise{
  // 通过 new Promise 进行实例化时,传入 executor 执行器函数
  constructor(executor){

    this.value = undefined; // 保存成功的原因,then中调用onFulfilled时传入
    this.reason = undefined; // 保存失败的原因,then中调用onFulfilled时传入
    this.state = PENDING;   // promise 状态,默认等待态
    // 成功 reslove 函数、失败reject函数,并传入executor
    const reslove = (value) =>{
      // 等待态 --> 成功态
      if(this.state === PENDING){
        this.value = value
        this.state = DULFILLED;
      }
    }
    const reject = (reason) =>{
      // 等待态 --> 失败态
      if(this.state === PENDING){
        this.reason = reason
        this.state = REJECTED;
      }
    }
    
    // 立即执行 executor 执行器函数,通过 try...catch... 进行异常捕捉;
    try{
      executor(reslove, reject);
    }catch(e){
      reject(e)  // 有异常,调用 reject 更新为失败态
    }
  }
  
  // 定义 then 方法:包含两个参数 onFulfilled 和 onRejected;
  // 根据 Promise 状态,执行 onFulfilled 或 onRejected;
  then(onFulfilled, onRejected){
    // 成功态,调用 onFulfilled,传入成功 value
    if(this.state === DULFILLED){
      onFulfilled(this.value)
    } 
    // 失败态,执行 onRejected,传入失败 reason
    if(this.state === REJECTED){
      onRejected(this.reason)
    }
  }
}

// 导出 Promise 类供外部使用
module.exports = Promise; 

测试 promise 基础功能:

// 1,引入简版 Promise
let Promise = require('./source/promise');  

// 2.实例化 Promise 并传入 executor 执行器函数(会立即被执行)
let promise = new Promise((resolve, reject)=>{
  console.log('promise')
  throw new Error("抛出错误");
})

//  3,then 方法
promise.then((value)=>{
  console.log('success', value) 
},(reason)=>{
  console.log('err', reason)
})
console.log('ok')

// 执行结果
promise
err Error: 抛出错误

这样,就完成了一个简版(示意版本)的 Promise;


五,结尾

本篇,根据对 Promise 的分析和了解,实现了一个简版 Promise,主要涉及以下内容:

  • Promise 的实现思路;
  • Promise A+ 规范(简版);
  • Promise 简版实现和功能测试;

下一篇,翻译并理解 Promise A+ 规范;


维护日志

  • 20211120:
    • 修改错别字