• Promise实现原理学习笔记


           Promise 是异步编程的一种解决方案,用于解决传统编程中的回调地狱问题。ES6对其标准用法进行了统一,并原生提供了Promise对象。Promise对象有三种状态:等待态(Pending)、执行态(Fulfilled)和拒绝态(Rejected),且状态的转换是不可逆的,只能由Pending转换为FulfilledRejected,而FulfilledRejected之间是不能互相转换的

           Promise对象表示一个异步操作的执行结果,通过then方法与其进行交互,then方法使用两个回调函数作为参数,用于接收Promise成功执行的结果或者被拒绝执行的原因。

    基本用法:

    function onFulfilled(value) {
      console.log(value)
    }
    function onRejected(error) {
      console.log(error)
    }
    
    const promise = new Promise(function(resolve, reject) {
      // ...异步操作
      if (/* 操作成功 */) {
        resolve(value);
      } else {
        reject(error);
      }
    });
    
    promise.then(onFulfilled, onRejected);

    上面就是Promise的一个基本用法,更详细的使用说明请参考阮一峰ECMAScript 6入门之Promise对象

    原理说明:

      通过上面的基本用法可以看出,Promise是一个构造函数,该构造函数接收一个函数作为参数,为了便于说明我们把该函数命名为executorexecutor有两个参数resolvereject,这两个参数也都是函数。Promise对象上还必须有一个then方法,该方法也接收两个函数作为参数。

    基于以上说明,我们先给出一个Promise构造函数的简单实现框架如下:

    function Promise(executor) {
      function resolve(value) {
       }
    function reject(error) {
       } executor(resolve, reject) } Promise.prototype.then
    = function(onFulfilled, onRejected) {
    }

    Promise的核心特点之一就是状态的转换,所以我们要在框架中体现出转换的变化,如下:

    function Promise(executor) {
      this.status = 'pending'
    
      function resolve(value) {
        if(this.status == 'pending') {
          this.status = 'fulfilled'
        }
      }
    
      function reject(error) {
        if(this.status == 'pending') {
          this.status = 'rejected'
        }
      }
    
      executor(resolve, reject)
    }
    
    Promise.prototype.then = function(onFulfilled, onRejected) {
      if(this.status == 'fulfilled') {
        onFulfilled()
      }
    
      if(this.status == 'rejected') {
        onRejected()
      }
    }

    此时该Promise也仅仅只是能够处理同步操作,就是说当我们调用then方法时executor已经处理结束,状态已经由pending转换为fulfilledrejected,但这肯定是不可以的!!!所以在调用then方法时我们还得考虑状态为pending的情况,但是在状态为pending的情况下调用onFulfilledonRejected回调函数是完全没有意义的,所以我们只能先将对应的回调函数缓存起来,等到状态改变之后再调用执行。如下:

    function Promise(executor) {
      this.status = 'pending'
      this.value = null
      this.error = null
      this.onFulfilledCallbacks = []
      this.onRejectedCallbacks = []
    
      function resolve(value) {
        if(this.status == 'pending') {
          this.status = 'fulfilled'
          this.value = value
          this.onFulfilledCallbacks.forEach(function(callback) {
            callback()
          });
        }
      }
    
      function reject(error) {
        if(this.status == 'pending') {
          this.status = 'rejected'
          this.error = error
          this.onRejectedCallbacks.forEach(function(callback) {
            callback()
          });
        }
      }
    
      executor(resolve, reject)
    }
    
    Promise.prototype.then = function(onFulfilled, onRejected) {
      if(this.status == 'fulfilled') {
        onFulfilled(this.value)
      }
    
      if(this.status == 'rejected') {
        onRejected(this.error)
      }
    
      if(this.status == 'pending') {
        this.onFulfilledCallbacks.push(onFulfilled(this.value))
        this.onRejectedCallbacks.push(onRejected(this.error))
      }
    }

      至此,一个简单的Promise实现就算完成了,暂时没有考虑一些校验和错误处理。其实核心的实现原理就是状态机制+观察者模式

    参考文献:

      1、【翻译】Promises/A+规范

      2、30分钟,让你彻底明白Promise原理

      3、Promise原理详解

  • 相关阅读:
    还在使用golang 的map 做Json编码么?
    Golang 性能测试(2) 性能分析
    golang 性能测试 (1) 基准性能测试
    消息队列 NSQ 源码学习笔记 (五)
    消息队列 NSQ 源码学习笔记 (四)
    消息队列 NSQ 源码学习笔记 (三)
    消息队列 NSQ 源码学习笔记 (二)
    消息队列 NSQ 源码学习笔记 (一)
    你不知道的空格
    Supervisor 使用和进阶4 (Event 的使用)
  • 原文地址:https://www.cnblogs.com/fengyuexuan/p/12187810.html
Copyright © 2020-2023  润新知