zoukankan      html  css  js  c++  java
  • Promise详解(转载)

    Promise表示一个异步操作的最终结果。与Promise最主要的交互方法是通过将函数传入它的then方法从而获取得Promise最终的值或Promise最终最拒绝(reject)的原因。

    一、promise的状态

    一个Promise必须处在其中之一的状态:pending, fulfilled 或 rejected.

    • 如果是pending状态,则promise:

      • 可以转换到fulfilled或rejected状态。
    • 如果是fulfilled状态,则promise:

      • 不能转换成任何其它状态。
      • 必须有一个值,且这个值不能被改变。
    • 如果是rejected状态,则promise可以:

      • 不能转换成任何其它状态。
      • 必须有一个原因,且这个值不能被改变。

    ”值不能被改变”指的是其identity不能被改变,而不是指其成员内容不能被改变。

    二、then方法

    一个Promise必须提供一个then方法来获取其值或原因。

    Promise的then方法接受两个参数:

    promise.then(onFulfilled, onRejected)
    
    1. onFulfilled 和 onRejected 都是可选参数:

      1. 如果onFulfilled不是一个函数,则忽略之。
      2. 如果onRejected不是一个函数,则忽略之。
    2. 如果onFulfilled是一个函数:

      1. 它必须在promise fulfilled后调用, 且promise的value为其第一个参数。
      2. 它不能在promise fulfilled前调用。
      3. 不能被多次调用。
    3. 如果onRejected是一个函数,

      1. 它必须在promise rejected后调用, 且promise的reason为其第一个参数。
      2. 它不能在promise rejected前调用。
      3. 不能被多次调用。
    4. onFulfilled 和 onRejected 只允许在 execution context 栈仅包含平台代码时运行. [3.1].
    5. onFulfilled 和 onRejected 必须被当做函数调用 (i.e. 即函数体内的 this 为undefined). [3.2]
    6. 对于一个promise,它的then方法可以调用多次.

      1. promise fulfilled后,所有onFulfilled都必须按照其注册顺序执行。
      2. promise rejected后,所有OnRejected都必须按照其注册顺序执行。
    7. then 必须返回一个promise [3.3].

      promise2 = promise1.then(onFulfilled, onRejected);
      
      1. 如果onFulfilled 或 onRejected 返回了值x, 则执行Promise 解析流程[[Resolve]](promise2, x).
      2. 如果onFulfilled 或 onRejected抛出了异常e, 则promise2应当以ereason被拒绝。
      3. 如果 onFulfilled 不是一个函数且promise1已经fulfilled,则promise2必须以promise1的值fulfilled.
      4. 如果 OnReject 不是一个函数且promise1已经rejected, 则promise2必须以相同的reason被拒绝.
    三、promise解析过程

    Promise解析过程 是以一个promise和一个值做为参数的抽象过程,可表示为[[Resolve]](promise, x). 过程如下;

    1. 如果promise 和 x 指向相同的值, 使用 TypeError做为原因将promise拒绝。
    2. 如果 x 是一个promise, 采用其状态 [3.4]:

      1. 如果x是pending状态,promise必须保持pending走到x fulfilled或rejected.
      2. 如果x是fulfilled状态,将x的值用于fulfill promise.
      3. 如果x是rejected状态, 将x的原因用于reject promise..
    3. 如果x是一个对象或一个函数:

      1. 将 then 赋为 x.then. [3.5]
      2. 如果在取x.then值时抛出了异常,则以这个异常做为原因将promise拒绝。
      3. 如果 then 是一个函数, 以xthis调用then函数, 且第一个参数是resolvePromise,第二个参数是rejectPromise,且:

        1. 当 resolvePromise 被以 y为参数调用, 执行 [[Resolve]](promise, y).
        2. 当 rejectPromise 被以 r 为参数调用, 则以r为原因将promise拒绝。
        3. 如果 resolvePromise 和 rejectPromise 都被调用了,或者被调用了多次,则只第一次有效,后面的忽略。
        4. 如果在调用then时抛出了异常,则:

          1. 如果 resolvePromise 或 rejectPromise 已经被调用了,则忽略它。
          2. 否则, 以e为reason将 promise 拒绝。
      4. 如果 then不是一个函数,则 以x为值fulfill promise
    4. 如果 x 不是对象也不是函数,则以x为值 fulfill promise
    四、promise封装异步请求
      
    // 以小程序为例
    runAsync1: function() {
      let promise = new Promise((resolve, reject) => {
        //请求
      setTimeout(() => {
        console.log('执行完成1');
        resolve('随便什么数据1');
      }, 1000)
      })
      return promise
    },
    runAsync2: function() {
      let promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        //请求
        console.log('执行完成2');
        resolve('随便什么数据2');
      }, 500)
      })
      return promise
    },
    runAsync3: function() {
      let promise = new Promise((resolve, reject) => {
      setTimeout(() => {
        //请求
        console.log('执行完成3');
        resolve('随便什么数据3');
      }, 1000)
      })
      return promise
    },
     
    // promise核心链式操作的用法
    this.runAsync1().then((data) => {
      console.log(data);
      return this.runAsync2()
    })
    .then((data) => {
      console.log(data);
      return this.runAsync3()
    })
    .then((data) => {
      console.log(data);
    })

    //all用法:在所有异步操作执行完后才执行回调(谁跑的慢,以谁为准执行回调)
    Promise.all([this.runAsync1(), this.runAsync2(), this.runAsync3()])
    .then((data) => {
    console.log(data)
    })
     
    // race用法:(谁跑的快,以谁为准执行回调)
    Promise.race([this.runAsync1(), this.runAsync2(), this.runAsync3()])
    .then((data) => {
      console.log(data)
    })
  • 相关阅读:
    C++ ORM ODB 入门(三)
    C++ ORM ODB 入门介绍(二)
    最简便的MySql数据库备份方法
    快速高效的破解MySQL本地和远程密码
    C++ ORM ODB 入门介绍(一)
    NeHe OpenGL教程 第三十九课:物理模拟
    NeHe OpenGL教程 第三十八课:资源文件
    NeHe OpenGL教程 第三十七课:卡通映射
    NeHe OpenGL教程 第三十六课:从渲染到纹理
    NeHe OpenGL教程 第三十五课:播放AVI
  • 原文地址:https://www.cnblogs.com/ycyh1314/p/10570091.html
Copyright © 2011-2022 走看看