乐趣区

关于promise:PromisesA规范

Promises/A+ 标准
一个凋谢的规范,实现者为开发者提供的可操作 JavaScript promise。
promise 代表着异步操作最终后果。和 promise 交互的次要形式是通过其 then 办法,then 办法通过注册回调以承受 promise 的最终值或者 promise 无奈实现的起因。
该标准详细描述了 then 办法的行为,提供了一个可互操作的根底,所有 Promises/A+ 统一的 promise 实现都能够依赖于它来提供。因而,标准应该被认为是十分稳固的。只管 Promises/A+ 组织偶然会对本标准进行一些小的向后兼容更改,以解决新发现的小问题,但只有通过认真思考、探讨和测试后,咱们才会集成较大或向后不兼容的更改。
从历史上看,Promises/A+说明了晚期 Promise/A 提案的行为条款,将其扩大到涵盖事实上的行为,并省略了未指定或有问题的局部。
最初,外围 Promises/A+ 标准不波及如何创立、实现或回绝 promise,而是抉择集中于提供可互操作的 then 办法。将来在配套标准中的工作可能会波及到这些主题。

1. 术语

  1. “promise”是 then 行为合乎本标准的对象或函数。
  2. “thenable”是定义 then 办法的对象或函数。
  3. “值”是任何非法的 JavaScript 值(包含 undefined,ableable 或 promise)。
  4. “exception”是应用该 throw 语句引发的值。
  5. “起因”是一个值,该值批示为什么回绝 promise。

2. 要求

2.1 promise 状态

promise 必须处于以下三种状态之一:待定,已实现或被回绝。

  1. 待定时,promise:可能会转换为已实现或已回绝状态。
  2. 当实现时,promise:

    1. 不得过渡到其余任何状态。
    2. 必须具备一个值,该值不能更改。
  3. 当被回绝时,promise:

    1. 不得过渡到其余任何状态。
    2. 必须有一个理由,不能扭转。
  4. 在此,“不得更改”是指不变的身份(即 ===),但并不示意深层的不变性。

2.2 then 办法

promise 必须提供一种 then 拜访其以后或最终价值或起因的办法。
允诺的 then 办法承受两个参数:

        promise.then(onFulfilled, onRejected)
  1. 这两个 onFulfilled 和 onRejected 可选的参数:

    1. 如果 onFulfilled 不是函数,则必须将其疏忽。
    2. 如果 onRejected 不是函数,则必须将其疏忽。
  2. 如果 onFulfilled 是一个函数:

    1. 必须在 promise 实现后调用,以 promise 的值作为第一个参数。
    2. 在 promise 实现之前肯定不能调用它。
    3. 不能屡次调用它。
  3. 如果 onRejected 是一个性能,

    1. 必须在 promise 被回绝之后以 promise 的理由作为第一个参数调用它。
    2. 在 promise 被回绝之前不能调用它。
    3. 不能屡次调用它。
  4. onFulfilled 或 onRejected 在执行上下文堆栈仅蕴含平台代码之前不得调用。[3.1]。
  5. onFulfilled 并且 onRejected 必须作为函数调用(即没有 this 值)。[3.2]
  6. then 可能在同一诺言中屡次被调用。

    1. 如果 / 何时 promise 实现,则所有各自的 onFulfilled 回调必须依照其对的原始调用的程序执行 then。
    2. 如果 / 何时 promise 被回绝,则所有各自的 onRejected 回调必须依照其对的原始调用的程序执行 then。
  7. then 必须返回一个 promise[3.3]。

    1. 如果有一个 onFulfilled 或 onRejected 返回一个值 x,请运行 Promise Resolution Procedure [[Resolve]](promise2, x)。
    2. 如果任何一个 onFulfilled 或 onRejected 引发异样 e,则 promise2 必须 e 以其为理由予以回绝。
    3. 如果 onFulfilled 不是函数且 promise1 已实现,则 promise2 必须应用与雷同的值来实现 promise1。
    4. 如果 onRejected 不是性能而 promise1 被回绝,则 promise2 必须以与雷同的理由将其回绝 promise1。
       promise2 = promise1.then(onFulfilled, onRejected);

2.3promise 解决程序

promise 解决过程是一个形象的操作作为输出一个 promise 和一个值,它示意咱们作为 [[Resolve]](promise, x)。如果 x 是可能的,则在行为至多相似于诺言的假如下,尝试 promise 采纳的状态。否则,它将满足 value。xxpromisex
只有对约定的实现公开 Promises / A + 兼容的 then 办法,对约定的实现就能够实现互操作。它还容许 Promises / A + 实现以正当的 then 办法“异化”不合格的实现。
要运行[[Resolve]](promise, x),请执行以下步骤:

  1. 如果 promise 和 x 援用雷同的对象,promise 则以回绝 TypeError 为理由。
  2. 如果 x 是一个 promise,则采纳其状态[3.4]:

    1. 如果 x 未决,则 promise 必须放弃未决状态,直到 x 实现或被回绝。
    2. 如果 / 何时 x 满足,promise 则以雷同的值满足。
    3. 如果 / 何时 x 被回绝,promise 则以雷同的理由回绝。
  3. 否则,如果 x 是对象或函数,

    1. then 是 x.then。[3.5]
    2. 如果检索属性 x.then 中抛出的异样的后果 e,回绝 promise 与 e 作为的起因。
    3. 如果 then 是函数,请应用 xas this,第一个参数 resolvePromise 和第二个参数进行调用 rejectPromise,其中:

      1. 如果 / 何时 resolvePromise 应用值调用 y,请运行[[Resolve]](promise, y)。
      2. 如果 / 当 rejectPromise 是带一个理由 r,回绝 promise 与 r。
      3. 如果同时调用 resolvePromise 和 rejectPromise,或者对同一参数进行了屡次调用,则第一个调用优先,而所有其余调用均被疏忽。
      4. 如果调用 then 引发异样 e,

        1. 如果 resolvePromise 或 rejectPromise 曾经被调用,则疏忽它。
        2. 否则,回绝 promise 与 e 作为的起因。
    4. 如果 then 不是一个函数,实现 promise 用 x。
  4. 如果 x 不是一个对象或性能,实现 promise 与 x。

如果应用参加循环的可循环链的可扩大物解决了诺言,使得 [[Resolve]](promise, thenable) 最终的递归性质最终导致 [[Resolve]](promise, thenable) 再次被调用,则遵循上述算法将导致有限递归。激励但不是必须的实现,以检测这种递归并 promise 以提供信息 TypeError 的理由回绝。[3.6]

3. 笔记

  1. 这里的“平台代码”是指引擎,环境和 promise 实现代码。实际上,此要求可确保在调用事件循环之后并应用新堆栈 onFulfilled 并 onRejected 异步执行 then。这能够通过“宏工作”机制(例如 setTimeout 或 setImmediate)或“微工作”机制(例如 MutationObserver 或)来实现 process.nextTick。因为 promise 实现被视为平台代码,因而它自身可能蕴含一个任务调度队列或“蹦床”,在其中调用处理程序。
  2. 也就是说,在严格模式下 this 将呈现 undefined 在其中;在懒惰(sloppy)模式下,它将是全局对象。
  3. promise2 === promise1 如果实现满足有要求,则实现能够容许。每个实现都应记录其是否能够生产 promise2=== promise1 以及在什么条件下生产。
  4. 通常,只有 x 它来自以后的实现,才晓得这是一个真正的 promise。本节容许应用特定于实现的形式来采纳已知合乎 promise 的状态。
  5. 首先存储对的援用 x.then,而后测试该援用,而后调用该援用的过程防止了对该 x.then 属性的屡次拜访。此类预防措施对于确保访问者属性的一致性十分重要,因为访问者属性的值在两次检索之间可能会发生变化。
  6. 实现应不设置 thenable 链的深度任何限度,并假如超出任何限度递归将是有限的。只有真正的周期能力导致 TypeError; 如果遇到有限多个不同的罐头,则永远递归是正确的行为。

原文地址

退出移动版