自定义Promise之构造函数的实现

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

本文介绍了如何简单去实现一个Promise。

1.1 定义整体结构

  1. 首先,我们需要定义整个自定义Promise函数的整体结构,并将整个结构包裹在一个IIFE自执行函数中,通过传入参数window,将自定义的Promise函数绑定到全局对象window上,并暴露出去。

  2. 其次,定义好需要实现常用的方法:Promise的构造函数,Promise原型对象上的then方法,catch方法,以及Promise函数对象上的resolve,reject,all和race方法

    /*
    自定义 Promise
    */
    (function (window) {
    
       /*
       Promise 构造函数
       executor: 内部同步执行的函数 (resolve, reject) => {}
       */
       function Promise(executor) { }
    
       /*
       为 promise 指定成功/失败的回调函数
       函数的返回值是一个新的 promise 对象
       */
       Promise.prototype.then = function (onResolved, onRejected) { }
    
       /*
       为 promise 指定失败的回调函数
       是 then(null, onRejected)的语法糖
       */
       Promise.prototype.catch = function (onRejected) { }
    
       /*
       返回一个指定了成功 value 的 promise 对象
       */
       Promise.resolve = function (value) { }
    
       /*
       返回一个指定了失败 reason 的 promise 对象
       */
       Promise.reject = function (reason) { }
    
       /*
       返回一个 promise, 只有 promises 中所有 promise 都成功时, 才最终成功, 只要有一个失败就直接
       失败
       */
       Promise.all = function (promises) { }
    
       /*
       返回一个 promise, 一旦某个 promise 解决或拒绝, 返回的 promise 就会解决或拒绝。
       */
       Promise.race = function (promises) { }
    
       // 暴露构造函数
       window.Promise = Promise
    })(window)

1.2 Promise 构造函数的实现

1.2.1 执行器函数和resolve、reject函数

根据原生的Promise可知,Promise构造函数的参数为一个同步执行的执行器函数,且这个执行器函数有两个参数类型为函数的参数。

第一个参数为将Promise实例对象的状态改为fulfilled状态的函数,第二个参数为将Promise实例对象的状态改为rejected状态的函数。

代码实现:

/*
  Promise 构造函数
  executor: 内部同步执行的函数 (resolve, reject) => {}
*/
function Promise(executor) {
  // resolve函数,将实例对象的状态转为fulfilled
  function resolve(value) {

  }

  // resolve函数,将实例对象的状态转为rejected
  function reject(reason) {

  }

  // 同步调用executor执行器函数
  executor(resolve, reject)
}

1.2.2 resolve和reject函数的实现

设置实例对象的初始状态和初始值

resolve和reject函数内部都是将Promise实例对象的状态修改为对应的状态,并设置对象的结果值。因此需先定义两个属性,分别为实例对象的初始状态和初始值

/*
  Promise 构造函数
  executor: 内部同步执行的函数 (resolve, reject) => {}
*/
function Promise(executor) {
  // 定义实例对象的状态和值
+ this.PromiseState = 'pending'
+ this.PromiseResult = undefined

  // resolve函数,将实例对象的状态转为fulfilled
  function resolve(value) {

  }

  // resolve函数,将实例对象的状态转为rejected
  function reject(reason) {

  }

  // 同步调用executor执行器函数
  executor(resolve, reject)
}

resolve和reject函数内部实现

/*
  Promise 构造函数
  executor: 内部同步执行的函数 (resolve, reject) => {}
*/
function Promise(executor) {
  // 定义实例对象的状态和值
  this.PromiseState = 'pending'
  this.PromiseResult = undefined

  // resolve函数,将实例对象的状态转为fulfilled
  function resolve(value) {
    // 修改实例对象的状态
+   this.PromiseState = 'fulfilled'
    // 设置实例对象结果值
+   this.PromiseResult = value
  }

  // resolve函数,将实例对象的状态转为rejected
  function reject(reason) {
+   this.PromiseState = 'rejected'
+   this.PromiseResult = reason
  }

  // 同步调用executor执行器函数
  executor(resolve, reject)
}

this指向的问题

通过上述代码测试运行会发现一个问题,再执行resolve或reject函数后,Promise实例对象的状态以及结果并没有发生改变。原因是因为resolve和reject函数是在外部调用的,其内部的this不是指向实例对象,而是会默认执行全局对象window,因此需要修改代码,保存this的指向

function Promise(executor) {
    // 定义实例对象的状态和值
    this.PromiseState = 'pending'
    this.PromiseResult = undefined

    // 保存this指向
+   const self = this

    // resolve函数,将实例对象的状态转为fulfilled
    function resolve(value) {
      // 修改实例对象的状态
-     this.PromiseState = 'fulfilled'
+     self.PromiseState = 'fulfilled'
      // 设置实例对象结果值
-     this.PromiseResult = value
+     self.PromiseResult = value
    }

    // resolve函数,将实例对象的状态转为rejected
    function reject(reason) {
-      this.PromiseState = 'rejected'
+      self.PromiseState = 'rejected'
-      this.PromiseResult = reason
+      self.PromiseResult = reason
    }

    // 同步调用executor执行器函数
    executor(resolve, reject)
  }

1.2.3 throw抛出异常改变状态

通过原生Promise可知,当在执行器函数中抛出异常会立即将该实例对象的状态更改为rejected状态

function Promise(executor) {
    // 定义实例对象的状态和值
    this.PromiseState = 'pending'
    this.PromiseResult = undefined

    // 保存this指向
    const self = this

    // resolve函数,将实例对象的状态转为fulfilled
    function resolve(value) {
        // 修改实例对象的状态
        self.PromiseState = 'fulfilled'
        // 设置实例对象结果值
        self.PromiseResult = value
    }

    // resolve函数,将实例对象的状态转为rejected
    function reject(reason) {
        self.PromiseState = 'rejected'
        self.PromiseResult = reason
    }

    // 通过try...catch捕获异常
+    try {
+        // 同步调用executor执行器函数
+        executor(resolve, reject)
+    } catch (error) {
+       // 更改为rejected状态
+        reject(error)
+    }
}

1.2.4 状态只能转化一次

Promise实例对象状态只能由pending转为fulfilledreject,且只能转换一次,因此需要在resolve和reject函数添加判断条件

// resolve函数,将实例对象的状态转为fulfilled
function resolve(value) {
    // 只有pending状态才能修改状态
+   if(self.PromiseState !== 'pending') return
    // 修改实例对象的状态
    self.PromiseState = 'fulfilled'
    // 设置实例对象结果值
    self.PromiseResult = value
}

// resolve函数,将实例对象的状态转为rejected
function reject(reason) {
    // 只有pending状态才能修改状态
+   if(self.PromiseState !== 'pending') return
    self.PromiseState = 'rejected'
    self.PromiseResult = reason
}
暂无评论

发送评论 编辑评论


				
上一篇
下一篇