• 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原理详解

  • 相关阅读:
    用javascript实现html页面之间的参数传递
    个性的研究
    [luogu1967] 货车运输
    mscorwks.dll 没有被指定在Windows上运行,错误状态 0xc000012f
    dom4j解析xml时报:系统找不到指定路径
    The strip's most beautiful gril,rendezvous never a cover;
    无法在自定义编辑器中开发TransactSQL文件
    Default code generation is disabled for model。。。
    使用IE9艰辛历程之从什么网页都打不开到什么都秒开的传奇
    Metro IE10快捷方式 不小心删了
  • 原文地址:https://www.cnblogs.com/fengyuexuan/p/12187810.html
Copyright © 2020-2023  润新知