Promise原理

Promise的使用

 	Promise是ES6新增的内置类
    let p = new Promise(executor)  
      new Promise的时候,必须传递一个函数 executor ,传递的是其他类型值,则报错
      Promise必须被new执行,不能作为普通函数执行
    1. 实例的私有属性
      + [[PromiseState]]: "pending"   实例的状态 pending(准备)  fulfilled(成功)  rejected(失败)
      + [[PromiseResult]]: undefined  实例的值 undefined 成功的结果 失败的原因
    2. 实例的公有属性 Promise.prototype
      + then
      + catch
      + finally
      + Symbol(Symbol.toStringTag): "Promise"
    3. 把类做为普通对象,设置静态私有属性 Promise.xxx
      + all
      + any
      + race
      + resolve
      + reject
      + allSettled 返回一个 Promise,该 Promise 在所有传入的 Promise 已解决(无论成功还是失败)后解决,并返回一个包含每个 Promise 结果的数组,每个结果都有一个 status 字段,用于表示该 Promise 的状态


	Promise是用来管理异步编程的,我们经常把异步代码写在 executor 函数中

如何创建实例,以及如何修改其状态和值!!!

 	1、基于构造函数执行来创建实例
      let p = new Promise(executor)    
      + 立即执行executor函数,并且把Promise内部的resolve和reject方法作为参数传递给executor
      + resolve(value) 把实例的状态改为fulfilled,并且把value作为实例的值
      + reject(reason) 把实例的状态改为rejected,并且把reason作为实例的值
      + 如果executor函数抛出异常,则实例的状态改为rejected,并且把异常作为实例的值
      + 实例的状态一旦改变为fulfilled或rejected,则不可再改变

    2、基于Promise.resolve/reject方法创建实例
      + Promise.resolve(10) -> 创建一个状态为fulfilled,值是10的实例
      + Promise.reject(0) -> 创建一个状态为rejected,值是0的实例

    3、每一次执行then方法,都会返回一个 "全新的" Promise实例
      目的:实现 "then链" 机制
      let p2 = p1.then(onFulfilled, onRejected)
      + p2 是一个全新的Promise实例
      + p2的状态和值,取决于 onFulfilled或者onRejected 中的任意一个方法执行,我们观察执行的细节和结果,来决定p2的状态和值!!!
        + 首先看方法执行是否报错;如果执行报错,则p2的状态为rejected,值是报错的原因
        + 再看方法执行的返回值,是否是单独的promise实例【别名:pp】
          + 不是:则p2是fulfilled,值就是函数的返回值
          + 是:则p2的状态和值和pp的状态和值一致
          
 	4、Promise.all/any/race([promises])
      + 都会返回一个新实例 [别名p,或者称之为总的实例]
      + p的状态和值,取决于[promises]实例集合中的,每个实例的状态和值
      + [promises]集合中如果有一项不是promise实例,则要变为:状态为成功,值是本身的实例
      + all:所有实例为成功,总实例p才是成功[值:按集合顺序依次存储每一项的值],如果有一个实例为失败,则总实例p就是失败[值是失败项的值]
      + any:兼容性较差,它是ES靠后版本(11/12)中新增的;只要有一个成功,总实例p就是成功[值是成功这一项的值],如果所有项都是失败的,则总实例p才是失败的[值:all promise were rejected]
      + race:谁先处理完成就听谁的[把最快处理完毕的结果同步给总实例p]


    new Promise的时候会立即执行 executor (也就是立即处理了异步代码),然后根据异步代码的执行结果,执行onFulfilled或者onRejected方法

知道了实例的状态和值,有啥用?

	1、可以调用then方法,确定成功和失败各干什么
      p.then(onFulfilled, onRejected)
      + onFulfilled:在实例状态为成功的时候触发执行
      + onRejected:在实例状态为失败的时候触发执行
      + 都会把实例的值传递给这两个函数
      + 同一个实例,可多次调用then方法,最后会把每一次调用传递的onFulfilled或者onRejected都执行 也就是then链

    2、then链的穿透机制和catch/finally
      p.then(onFulfilled, onRejected)
      + 如果onFulfilled或者onRejected没有传递,则顺延至 "下一个then中" "同等状态" 要执行的方法
      + 原理:如果不设置对应的函数,Promise内部会默认设置一个函数,实现状态/值的顺延
      p.catch(onRejected)
      + 等同于p.then(null, onRejected)
      p.finally(onFinally)
      + 不论成功还是失败,都会把onFinally执行


	真实项目发开中,我们使用Promise,then中一般只放onFulfilled成功做的事情,在then链的末尾,设置一个catch,处理失败的情况;根据then链的穿透机制,中间不论那个环节出现失败的案例,都会顺延至最后一个catch进行失败的统一处理

下面是Promise的一些简单实现

;(function () {
  'use strict'
  function Promise(execute) {
    // 声明一个Promise对象
    var self = this,
      delayTimer = null
    // 判断execute是否为函数
    if (typeof execute !== 'function') throw new TypeError('Promise resolver' + execute + 'is not a function')
    // 判断Promise对象是否为undefined
    if (!(self instanceof Promise)) throw new TypeError('undefined is not a promise')

    // 初始化Promise对象的状态为pending
    self.state = 'pending'
    // 初始化Promise对象的值为undefined
    self.value = undefined
    // 初始化Promise对象的onFulfilledCallbacks和onRejectedCallbacks为空数组
    self.onFulfilledCallbacks = []
    self.onRejectedCallbacks = []

    // 声明一个change函数,用于更改Promise对象的状态和值
    var change = function change(State, Value) {
      // 如果Promise对象的状态不是pending,则返回
      if (self.state !== 'pending') return

      // 更改Promise对象的状态为State
      self.state = State
      // 更改Promise对象的值为Value
      self.value = Value

      // 如果Promise对象的状态是fulfilled,则清除delayTimer,并将onFulfilledCallbacks和onRejectedCallbacks数组中的每一项执行
      delayTimer = setTimeout(function () {
        clearTimeout(delayTimer)
        delayTimer = null
        var callbacks = self.state === 'fulfilled' ? self.onFulfilledCallbacks : self.onRejectedCallbacks,
          i = 0
        for (; i < callbacks.length; i++) {
          callbacks[i](self.value)
        }
      })
    }

    // 执行execute函数,更改Promise对象的状态和值
    try {
      execute(
        function resolve(result) {
          // 更改Promise对象的状态为fulfilled
          change('fulfilled', result)
        },
        function reject(reason) {
          // 更改Promise对象的状态为rejected
          change('rejected', reason)
        }
      )
    } catch (error) {
      // 更改Promise对象的状态为rejected
      change('rejected', error.message)
    }
  }

  function resolvePromise(promise, x, resolve, reject) {
    // 如果x是promise的实例,则抛出错误
    if (x === promise) throw new TypeError('Chaining cycle detected for promise #')
    // 如果x不是null且x的类型是一个对象或函数,则调用x的then方法
    if (x !== null && /^(object|function)$/i.test(typeof x)) {
      var then
      try {
        then = x.then
      } catch (err) {
        // 如果x的then方法抛出错误,则抛出错误
        reject(err)
      }

      // 如果x的then方法是一个函数,则调用then方法
      if (typeof then === 'function') {
        var called = false
        try {
          // 调用x的then方法,传入回调函数onfulfilled和onrejected
          then.call(
            x,
            function onfulfilled(y) {
              // 如果called为true,则返回
              if (called) return
              // 设置called为true
              called = true
              // 调用resolvePromise函数,传入promise,y,resolve和reject参数
              resolvePromise(promise, y, resolve, reject)
            },
            function onrejected(r) {
              // 如果called为true,则返回
              if (called) return
              // 设置called为true
              called = true
              // 调用reject函数,传入r
              reject(r)
            }
          )
        } catch (err) {
          // 如果called为true,则返回
          if (called) return
          // 调用reject函数,传入err
          reject(err)
        }
        return
      }
    }
    // 调用resolve函数,传入x
    resolve(x)
  }

  function common(callback, value, promise, resolve, reject) {
    try {
      // 调用回调函数,传入参数value
      var x = callback(value)
      // 调用resolvePromise函数,传入参数promise,x,resolve,reject
      resolvePromise(promise, x, resolve, reject)
    } catch (err) {
      // 调用reject函数,传入参数err
      reject(err)
    }
  }

  Promise.prototype = {
    constructor: Promise,
    // 定义then方法,用于处理promise的状态
    then: function then(onfulfilled, onrejected) {
      var self = this,
        delayTimer = null,
        promise
      // 如果onfulfilled不是函数,则将onfulfilled转换为函数
      if (typeof onfulfilled !== 'function') {
        onfulfilled = function onfulfilled(result) {
          return result
        }
      }
      // 如果onrejected不是函数,则将onrejected转换为函数
      if (typeof onrejected !== 'function') {
        onrejected = function onrejected(reason) {
          throw reason
        }
      }
      // 创建一个新的promise对象
      promise = new Promise(function (resolve, reject) {
        // 如果promise的状态为fulfilled,则调用common函数,将onfulfilled函数和promise对象作为参数传入
        switch (self.state) {
          case 'fulfilled':
            setTimeout(function () {
              common(onfulfilled, self.value, promise, resolve, reject)
            })
            break
          case 'rejected':
            setTimeout(function () {
              common(onrejected, self.value, promise, resolve, reject)
            })
            break
          default:
            // 将onfulfilledCallbacks和onRejectedCallbacks添加到promise对象中
            self.onFulfilledCallbacks.push(function (result) {
              setTimeout(function () {
                common(onfulfilled, result, promise, resolve, reject)
              })
            })
            self.onRejectedCallbacks.push(function (reason) {
              setTimeout(function () {
                common(onrejected, reason, promise, resolve, reject)
              })
            })
        }
      })
      // 返回promise对象
      return promise
    },
    // 定义catch方法,用于处理promise的状态
    catch: function mycatch(onrejected) {
      // 返回promise对象
      return this.then(null, onrejected)
    }
    // 定义finally方法,用于处理promise的状态
    // finally: function myfinally () { }
  }

  if (typeof Symbol !== 'undefined') Promise.prototype[Symbol.toStringTag] = 'Promise'

  Promise.resolve = function resolve(result) {
    // 返回一个新的Promise对象,该对象的resolve方法会把result作为参数传入
    return new Promise(function (resolve) {
      resolve(result)
    })
  }

  Promise.reject = function reject(_, reason) {
    // 定义一个Promise对象,用于拒绝
    return new Promise(function (reject) {
      // 调用reject函数,拒绝reason
      reject(reason)
    })
  }

  Promise.all = function all(promises) {
    // 判断promises是否是数组
    if (!Array.isArray(promises))
      throw new TypeError('promises must be an Array')
      // 初始化变量
    ;(varn = 0), (results = [])
    // 返回一个Promise对象
    return new Promise(function (resolve, reject) {
      // 遍历promises数组
      for (var i = 0; i < promises.length; i++) {
        // 将promises数组中的每一项转换成Promise对象
        ;(function (i) {
          var promise = promises[i]
          // 判断promise是否是Promise对象
          if (!isPromise(promise)) promise = Promise.resolve(promise)
          // 将promise对象转换成Promise对象
          promise
            .then(function (result) {
              // 将promise对象的结果赋值给变量n
              n++
              // 将promise对象的结果赋值给results数组
              results[i] = result
              // 如果promises数组的长度大于等于promise对象的结果,则resolve results数组
              if (n >= promises.length) resolve(results)
            })
            .catch(function (reason) {
              // 将promise对象的异常赋值给reject
              reject(reason)
            })
        })(i)
      }
    })
  }

  Promise.deferred = function deferred() {
    // 定义一个空对象
    var result = {}
    // 创建一个Promise对象,并将resolve和reject方法赋值给result对象
    result.promise = new Promise(function (resolve, reject) {
      // 将resolve和reject方法赋值给result对象
      result.resolve = resolve
      result.reject = reject
    })
    // 返回result对象
    return result
  }

  function isPromise(x) {
    // 判断x是否为null或者是一个对象或者函数
    if (x !== null && /^(object|function)$/i.test(typeof x)) {
      // 判断x是否为Promise对象
      if (typeof x.then === 'function') {
        // 如果是Promise对象,返回true
        return true
      }
    }
    // 否则返回false
    return false
  }

  // 如果window不存在,则将Promise设置为Promise
  if (typeof window !== 'undefined') window.Promise = Promise
  // 如果Symbol不存在,则将Promise的toStringTag设置为Promise
  if (typeof Symbol !== 'undefined') Promise.prototype[Symbol.toStringTag] = 'Promise'
})()

你可能感兴趣的:(javascript,前端)