Promises/A+ 细读

翻译一下:# Promises/A+

参考文章:# Promise/A+ 中文翻译

前言

An open standard for sound, interoperable JavaScript promises---by implementers, for implementers.

一个可靠的、可交互的JavaScript Promise的开放标准------由开发者制定,供开发者参考。

A promise represents the eventual result of an asynchronous operation. The primary way of interacting with a promise is through its then method, which registers callbacks to receive either a promise's eventual value or the reason why the promise cannot be fulfilled.

翻译 :promise表示异步操作的最终结果。与promise交互的主要方式是通过它的then方法,该方法注册回调以接收promise的最终返回值或无法实现promise的原因。

译者(意译) :一个promise就是一个异步操作的最终结果,有promise的地方一定会有异步操作。

和promise交互,只能通过 promise.then(res=>{}),res就是promise的最终返回值,如果报错,res就是错误原因。

This specification details the behavior of the then method, providing an interoperable base which all Promises/A+ conformant promise implementations can be depended on to provide.

As such, the specification should be considered very stable.

Although the Promises/A+ organization may occasionally revise this specification with minor backward-compatible changes to address newly-discovered corner cases, we will integrate large or backward-incompatible changes only after careful consideration, discussion, and testing.

翻译软件 :该规范详细描述了then方法的行为,提供了一个可互操作的基础,因此所有符合 Promises/A+ 的 promise 实现都可以依赖该基础(标准)。

因此,该规范应被视为非常稳定。

虽然制定Promises/A+规范的组织可能偶尔会修改这个规范,进行少量向后兼容的更改,以解决新发现的极端情况,但我们只会在仔细考虑、讨论和测试之后才会集成大型或向后不兼容的更改。

译者(意译) :这个规范规定了promise.then()必须完成的一些行为,如果你想自己实现一个 promise ,那么这个标准的存在就是你可以自己实现的基础(或者说,没有这个标准,你也无从下手不是)。

即使这个标准会做修改,大框架也是不变的,只是为了解决一些极端情况下的bug(类似一些软件打补丁,总会向后兼容的。

Historically, Promises/A+ clarifies the behavioral clauses of the earlier Promises/A proposal, extending it to cover de facto behaviors and omitting parts that are underspecified or problematic.

翻译软件:从历史上看,Promises/A+ 阐明了早期 Promises/A 提案的行为条款,扩展 Promises/A+ 以涵盖事实上的行为,并省略了未明确或有问题的部分。

译者(意译):为了更明确,Promises/A+ 重新解释了以前 Promises/A 提案的行为条款。并且把【目前已经实现了,但没有写在标准里的一些行为】加入到了标准中,同时,新的标准省略了一些【不明确】或者【有问题】的部分。

Finally, the core Promises/A+ specification does not deal with how to create, fulfill, or reject promises, choosing instead to focus on providing an interoperable then method.

Future work in companion specifications may touch on these subjects.

翻译软件 :最后,核心Promises/A+规范没有处理如何createfulfill 、或者 reject promises 的部分,而是选择专注于提供一个可交互的then方法。

未来在配套规范中的工作可能会涉及这些主题。

译者(意译) :核心Promises/A+规范主要是告诉我们then方法是怎么实现的(或者说then方法需要实现什么功能。

# Promise/A+ 中文翻译的作者说:

arduino 复制代码
由此可以看出 Promises/A+ 规范目前的核心是规范 then 方法,
并没有对【如何实现 promise 】以及【如何改变 promise 的状态】进行限制。

但我不太懂这句话应用场景是什么。

是只要我实现了这个标准我的就是promise了吗?是我可以自由改变promise的状态吗?

正文

1.Terminology

  1. "promise" is an object or function with a then method whose behavior conforms to this specification.
  2. "thenable" is an object or function that defines a then method.
  3. "value" is any legal JavaScript value (including undefined, a thenable, or a promise).
  4. "exception" is a value that is thrown using the throw statement.
  5. "reason" is a value that indicates why a promise was rejected.

翻译

术语:

  1. "promise " 是一个有符合当前规范的then方法的 object 或者 function
  2. "thenable " 是定义(了)then方法的 object 或者 function
  3. "value " 是 JavaScript 的任意合法值(包括 undefined, thenable , promise)。
  4. "exception " 是通过throw方法(语句)被抛出的 value
  5. "reason " 是说明一个 promise 被 rejected 的原因的 value

2.Requirements

2.1.Promise States

A promise must be in one of three states: pending, fulfilled, or rejected.

  • 2.1.1. When pending, a promise:
    • 2.1.1.1. may transition to either the fulfilled or rejected state.
  • 2.1.2. When fulfilled, a promise:
    • 2.1.2.1. must not transition to any other state.
    • 2.1.2.2. must have a value, which must not change.
  • 2.1.3. When rejected, a promise:
    • 2.1.3.1. must not transition to any other state.
    • 2.1.3.2. must have a reason, which must not change.

Here, "must not change" means immutable identity (i.e. ===), but does not imply deep immutability.

翻译

promise 必须处于以下三种状态之一: pendingfulfilled, 或者 rejected

  • 2.1.1. 在 pending 状态下, promise:
    • 可以转换到 fulfilled 或者 rejected 状态。
  • 2.1.2. 在 fulfilled 状态下,promise:
    • 不能转换到其他任何状态。
    • 必须有一个值,并且不能改变这个值。
  • 2.1.3. 在 rejected 状态下,promise:
    • 不能转换到其他任何状态。
    • 必须有一个值,并且不能改变这个值。

在这里, "不能改变"意味着不可变的身份(即===),但并不意味着深度不变性。

译者(意译)

pending可以转换到其他两种状态。
fulfilledrejected不可以被改变状态,也不能改变promise的值。

"不能改变"意味着对象的引用地址不可变,但是内部结构什么的可以改变。

举例:下面这个就是【不具备深度不变】。因为引用地址相同。

js 复制代码
const person1 = { name: 'Alice', age: 30, hobbies: ['reading', 'painting'] };
// 创建 person2,将其引用地址设置为 person1 的
const person2 = person1 ;
// 尝试修改 person2 对象的属性或内容
person2.name = 'Bob'; // 修改对象属性值
person2.hobbies.push('gardening'); // 修改数组内容

console.log(person1); // 输出: { name: 'Bob', age: 30, hobbies: ['reading', 'painting', 'gardening'] }
console.log(person2); // 输出: { name: 'Bob', age: 30, hobbies: ['reading', 'painting', 'gardening'] }
console.log(person1 === person2); // 输出: true

2.2.The then Method

promise must provide a then method to access its current or eventual value or reason.

A promise's then method accepts two arguments:

arduino 复制代码
promise.then(onFulfilled, onRejected)
  1. Both onFulfilled and onRejected are optional arguments:

    1. If onFulfilled is not a function, it must be ignored.
    2. If onRejected is not a function, it must be ignored.
  2. If onFulfilled is a function:

    1. it must be called after promise is fulfilled, with promise's value as its first argument.
    2. it must not be called before promise is fulfilled.
    3. it must not be called more than once.
  3. If onRejected is a function,

    1. it must be called after promise is rejected, with promise's reason as its first argument.
    2. it must not be called before promise is rejected.
    3. it must not be called more than once.
  4. onFulfilled or onRejected must not be called until the execution context stack contains only platform code. [3.1].

  5. onFulfilled and onRejected must be called as functions (i.e. with no this value). [3.2]

  6. then may be called multiple times on the same promise.

    1. If/when promise is fulfilled, all respective onFulfilled callbacks must execute in the order of their originating calls to then.
    2. If/when promise is rejected, all respective onRejected callbacks must execute in the order of their originating calls to then.
  7. then must return a promise [3.3].

    ini 复制代码
     promise2 = promise1.then(onFulfilled, onRejected);
    1. If either onFulfilled or onRejected returns a value x, run the Promise Resolution Procedure [[Resolve]](promise2, x).
    2. If either onFulfilled or onRejected throws an exception e, promise2 must be rejected with e as the reason.
    3. If onFulfilled is not a function and promise1 is fulfilled, promise2 must be fulfilled with the same value as promise1.
    4. If onRejected is not a function and promise1 is rejected, promise2 must be rejected with the same reason as promise1.

翻译

then 方法

promise 必须提供一个then方法来获取它的 当前值最终值原因(rejected的原因)

promise的then方法接受两个参数,onFulfilledonRejected

arduino 复制代码
promise.then(onFulfilled, onRejected)
  1. onFulfilledonRejected 都是可选的参数:

    1.1. 如果 onFulfilled 不是函数,则忽略。

    1.2. 如果 onRejected 不是函数,则忽略。

  2. 如果 onFulfilled 是函数:

    2.1. 它必须在promise状态变成 fulfilled 之后调用,同时promisevalue 将作为它的第一个参数。

    2.2. 它不能在promise状态变成 fulfilled 之前调用。

    2.3. 它不能被调用多次。

  3. 如果 onRejected 是函数:

    3.1. 它必须在promise状态变成 rejected 之后调用,同时promisereason 将作为它的第一个参数。

    3.3. 它不能在promise状态变成 rejected 之前调用。

    3.4. 它不能被调用多次。

  4. 在执行上下文堆栈(execution context)只包含平台代码(同步代码)之前,不能调用onFulfilledonRejected。[3.1]。

  5. onFulfilled 或者 onRejected 必须以函数形式调用(即不能有this值)。[3.2]。

  6. then 方法可以被同一个 promise 调用多次。

    1. 如果或者当 promise 处于 fulfilled 状态, 所有自己的 onFulfilled 回调函数,必须要按照 then 注册的顺序被调用。
    2. 如果或者当 promise 处于 rejected 状态, 所有自己的 onRejected 回调函数,必须要按照 then 注册的顺序被调用。
  7. then 方法必须要返回 promise[3.3]

    ini 复制代码
    promise2 = promise1.then(onFulfilled, onRejected);
    1. 如果 onFulfilled 或者 onRejected 返回一个值 x ,则执行 Promise Resolution Procedure [[Resolve]](promise2, x)

    2. 如果 onFulfilled 或者 onRejected 抛出异常 e ,则必须以 e 为理由 reject promise2(译者:被抛出的异常 e 将会作为 onRejected 的参数 reason

    3. 如果 onFulfilled 不是一个 function ,同时promise1fulfilled 状态,promise2 必须用与promise1相同的 value 来变成 fulfilled 状态。

    4. 如果 onRejected 不是一个 function ,同时promise1rejected 状态,promise2 必须用与promise1相同的 value 来变成 rejected 状态。

译者(意译)

凡是promise都会有.then()方法,then的入参是两个回调函数onFulfilledonRejected

promise 的返回值将会是onFulfilledonRejected的入参。

如果是正常返回 ,那么返回值是onFulfilled的入参value

如果是通过异常被抛出 ,那么返回值是onRejected的入参reason

两个回调函数onFulfilledonRejected只会被调用一次。

并且
onFulfilled只能在promise 状态变成fulfilled 之后调用,其他状态不能调用。
onRejected只能在promise 状态变成rejected之后调用,其他状态不能调用。

这里讲一下4.在执行上下文堆栈......

这个指的就是宏任务微任务、事件循环的概念。可以看我这篇文章了解一下 : # JS事件循环Event Loop

详细看本文【3.1】目录

再说5.onFulfilled或者 onRejected必须以函数形式调用(即不能有this值),这个意思是他必须作为单纯的函数调用,而不能是obj.function()这种形式。

具体详见本文3.2

这个规定可以确保 onFulfilledonRejected 在执行时不依赖于特定的对象上下文,使得它们能够更加可靠和可预测。

再说一下7.then 方法必须要返回 promise......

学术一点的说法就是返回值穿透

如果在 then 方法中的回调函数返回一个值,无论是在onFulfilled状态还是onRejected状态,这个值将成为下一个 then 方法中对应状态的回调函数的参数。这样的传递确保了链式调用中数据的顺利传递和使用。

2.3.The Promise Resolution Procedure

The promise resolution procedure is an abstract operation taking as input a promise and a value, which we denote as [[Resolve]](promise, x). If x is a thenable, it attempts to make promise adopt the state of x, under the assumption that x behaves at least somewhat like a promise. Otherwise, it fulfills promise with the value x.

翻译: 这种处理方式允许promise实现互操作,只要它们公开了一个Promises/ a +兼容的then方法。

promise 解析过程 是一个抽象操作,输入一个promise 和一个value ,我们用[[Resolve]](promise, x)表示。

如果x是一个thenable ,它 (指代promise解析过程) 试图让promise采用 (呈现) x的状态,假设x的行为至少有点像一个promise

否则,它用x值将promise转换为fulfilled状态。

译者(意译)

Promise 对象的解析(或者说处理)过程。

在这个过程中,涉及到一个称为 [[Resolve]] 的抽象操作,用于处理 Promise 的 状态变更值的处理

当执行 [[Resolve]](promise, x) 操作时,它会接收两个参数:一个是 Promise 对象 promise,另一个是值 x

如果x是一个类似 Promise 的对象(也就是具有then方法的对象,被称为thenable ),那么[[Resolve]]操作会尝试使promise对象拥有(采用)和x相同的 状态 (pending、fulfilled、reject)、value (fulfilled状态下的值)、reason(rejected状态下的错误原因)。

arduino 复制代码
PS:如果promise状态变更处理异常、then方法实现存在问题(没有遵循规范)...可能会导致`promise` 无法准确地采用 `x` 的状态和值。

如果x不是一个类Promise对象(不是thenable),[[Resolve]]操作会用xpromise对象变成fulfilled的状态。

伪代码举例说明:

js 复制代码
// 创建一个 Promise 对象
let promise = new Promise((resolve, reject) => {
  // 在一段时间后成功解决这个 Promise,并传递一个值
  // `setTimeout` 可以代表实际开发中诸如网络请求、文件读取、定时任务等异步操作,这些操作不会立即完成,而是需要一定的时间。通过在 `setTimeout` 内部调用 `resolve`,可以模拟异步操作完成后,Promise 的状态变更。
  setTimeout(() => {
    resolve("Success!"); 
  }, 2000);
});

// 创建一个普通的值(字符串),不是 Promise 或 thenable 对象
let nonThenableValue = "非thenable的值";

// 使用 [[Resolve]] 操作,让 promise 对象采用非 Promise 的值来履行
[[Resolve]](promise, nonThenableValue);

// 此时 promise 对象已经成功地变为 fulfilled 状态
// 它的状态是已解决(fulfilled),并且输出 "非thenable的值"
promise.then((res) => {
  console.log(res); // 输出 "非thenable的值"
}).catch((err) => {
  console.error("err:", err);
});

总的来说,[[Resolve]] 操作是 Promise 解析过程中的一部分,负责处理传入的值,使得 Promise 能够按照规范的要求进行状态变更和最终的值处理。

This treatment of thenables allows promise implementations to interoperate, as long as they expose a Promises/A+-compliant then method. It also allows Promises/A+ implementations to "assimilate" nonconformant implementations with reasonable then methods.

翻译 : 这种对thenables的处理方式允许promise实现互操作,只要它们公开一个符合Promises/A+标准的then方法。它还允许 Promises/A+ 实现使用合理的 then 方法"同化"不一致的实现。

译者(意译)

互操作性:指的是不同的实现promise的框架,js原生按照标准实现了promise,还有一些其他框架。

我们自己写一套,按照标准实现了Promise,那它就是Promise。

To run [[Resolve]](promise, x), perform the following steps:

翻译 :要运行[[Resolve]](promise, x),请执行以下步骤:

  1. If promise and x refer to the same object, reject promise with a TypeError as the reason.

  2. If x is a promise, adopt its state [3.4]:

    1. If x is pending, promise must remain pending until x is fulfilled or rejected.
    2. If/when x is fulfilled, fulfill promise with the same value.
    3. If/when x is rejected, reject promise with the same reason.
  3. Otherwise, if x is an object or function,

    1. Let then be x.then. [3.5]

    2. If retrieving the property x.then results in a thrown exception e, reject promise with e as the reason.

    3. If then is a function, call it with x as this, first argument resolvePromise, and second argument rejectPromise, where:

      1. If/when resolvePromise is called with a value y, run [[Resolve]](promise, y).

      2. If/when rejectPromise is called with a reason r, reject promise with r.

      3. If both resolvePromise and rejectPromise are called, or multiple calls to the same argument are made, the first call takes precedence, and any further calls are ignored.

      4. If calling then throws an exception e,

        1. If resolvePromise or rejectPromise have been called, ignore it.
        2. Otherwise, reject promise with e as the reason.
    4. If then is not a function, fulfill promise with x.

  4. If x is not an object or function, fulfill promise with x.

翻译

  1. 如果promisex引用同一个对象,则用TypeError作为让promise变为rejected状态的reason (原因)。 (防止自身resolve自身,可能会导致循环引用或者其他问题)

  2. 如果 x 是 promise, 采用它的状态 [3.4]:

    1. 如果 xpending 状态, promise 必须保持 pending 状态直到x变为 fulfilled 或者 rejected状态。
    2. 如果/当 xfulfilled 状态, 用相同的valuepromise变更为fulfilled 状态。
    3. 如果/当 xrejected 状态, 用相同的reasonpromise变更为rejected 状态。
  3. 否则,如果x是一个对象或函数,

    1. then 方法 = x.then。 [3.5]

    2. 如果读取 x.then 方法导致抛出异常e, 将e作为reasonpromise变更为reject状态。

    3. 如果 then 是一个 function ,将x作为this调用它,第一个参数 resolvePromise, 第二个参数 rejectPromise,如下:

      1. 如果/当 resolvePromise 被调用,入参valuey, 执行[[Resolve]](promise, y).

      2. 如果/当 rejectPromise 被调用,入参reasonr,以rreasonpromise状态变更为rejected

      3. 如果resolvePromiserejectPromise都被调用,或者对同一参数进行了多次调用,则第一次调用优先 (仅第一次调用生效) ,任何后续调用都将被忽略。

      4. 如果调用then的时候抛出异常e

        1. 如果resolvePromise 或者 rejectPromise都已经被调用过,那么都忽略。
        2. 否则,以rreasonpromise状态变更为rejected
    4. 如果 then不是 function ,用xpromise变更为fulfilled 状态。

  4. 如果 x 不是对象或函数, 以 x 作为 value 让 promise 变成 fulfilled 状态。

If a promise is resolved with a thenable that participates in a circular thenable chain, such that the recursive nature of [[Resolve]](promise, thenable) eventually causes [[Resolve]](promise, thenable) to be called again, following the above algorithm will lead to infinite recursion.

Implementations are encouraged, but not required, to detect such recursion and reject promise with an informative TypeError as the reason. [3.6]

翻译 : 如果一个promise 是由一个环形thenable链(循环调用)中的 thenable 将状态变更为fulfilled 的,这种情况下,[[Resolve]](promise, thenable)的递归性质会让它再次被调用,遵循上述算法,会导致无限循环调用。

虽并非强行限制,但是鼓励开发者检测这种递归,并提供TypeErrorreasonpromise 状态变更为rejected 。[3.6]

3.Notes

这里 [3.1]就是上文里面被引用的地方的备注。

3.1

Here "platform code" means engine, environment, and promise implementation code.

In practice, this requirement ensures that onFulfilled and onRejected execute asynchronously, after the event loop turn in which then is called, and with a fresh stack.

This can be implemented with either a "macro-task" mechanism such as setTimeout or setImmediate, or with a "micro-task" mechanism such as MutationObserver or process.nextTick.

Since the promise implementation is considered platform code, it may itself contain a task-scheduling queue or "trampoline" in which the handlers are called.

翻译

这里的"平台代码" (platform code) 是指引擎、环境和promise实现代码

在实践中,这个要求确保onFulfilledonRejected在调用事件循环之后异步执行,并且使用一个新的堆栈。

这可以通过"宏任务"机制(如setTimeoutsetImmediate实现,也可以通过"微任务"机制(如MutationObserverprocess.nextTick)实现。

由于promise实现代码 被认为是平台代码,因此它本身可能包含一个任务调度队列或"trampoline " (直译:蹦床、跳板。猜测可能是一个队列或类似的结构) ,在该队列中调用处理程序。

译者补充

意思就是promise你可以实现成微任务或者宏任务。但不可以是同步任务。

现在都说 promise.then() 是微任务,实际上是因为微任务更方便、高效,是大家约定俗成的一致性选择。(当然,也是浏览器啥都是这么实现、支持的,大家没必要非自己实现一套异步的。

3.2

引用注释处

That is, in strict mode this will be undefined inside of them; in sloppy mode, it will be the global object.

翻译 :也就是说,在严格模式下, this 在其中将会被设置为 undefined ;在非严格模式下,它将会指向全局对象。

译者补充

在严格模式下,函数内部的 this 值为 undefined,这样可以避免意外的全局变量修改或出现不可预料的情况。

而在非严格模式下,函数内部的 this 默认指向全局对象,可能导致意外的全局变量修改或不符合预期的行为。

js 复制代码
'use strict';
function strictModeFunction() {
  console.log(this); // 输出: undefined
}
strictModeFunction(); // 在严格模式下调用函数
js 复制代码
function sloppyModeFunction() {
  console.log(this); // 输出: 全局对象(例如在浏览器中可能是 window)
}
sloppyModeFunction(); // 在非严格模式下调用函数

放在句中意思是:

在使用 Promise 的 then 方法时,onFulfilledonRejected 应该按照以下方式使用: promise.then(onFulfilled, onRejected);

而不是像这样使用(在这种情况下,如果回调函数内部依赖于 this,可能会导致问题):
promise.then(obj.onFulfilled, obj.onRejected);

这个规定可以确保 onFulfilledonRejected 在执行时不依赖于特定的对象上下文,使得它们能够更加可靠和可预测。

3.3

引用注释处

Implementations may allow promise2 === promise1, provided the implementation meets all requirements. Each implementation should document whether it can produce promise2 === promise1 and under what conditions.

翻译 :开发者可能实现promise 的时候会允许 promise2 === promise1的情况,前提是这种实现满足所有需求。每种实现都应该在文档中注明它是否可以、以及什么时候它可以提供promise2 === promise1

译者补充 :这个注释强调了关于 Promise 对象的行为。它指出,对于一个 Promise 对象 promise1,在某些情况下,实现可以允许 promise2promise1 是同一个对象(promise2 === promise1),前提是满足了所有规范要求。同时,每个实现都应该详细说明是否能够产生 promise2 === promise1,以及在什么情况下会出现这种情况。

简单来说,这段话暗示了对于 Promise 对象,某些实现可能允许在特定条件下对同一个 Promise 对象进行多次引用,使得这些引用指向同一个实际的 Promise 对象。

这种行为的允许可能依赖于实现的细节,比如对于 Promise 对象的缓存策略或者创建方式。一些实现可能会在特定情况下优化内存或提高性能而允许 promise2 === promise1,但并非所有的 Promise 实现都会这样做。

这句话的重点是:如果一个实现允许 promise2 === promise1 这种情况发生,那么这个实现应该清楚地记录下允许的条件和限制,确保开发者了解这一行为,并且能够准确地预测和理解其影响。

3.4

引用注释处

Generally, it will only be known that x is a true promise if it comes from the current implementation. This clause allows the use of implementation-specific means to adopt the state of known-conformant promises.

翻译 :一般来说,只有当x来自当前实现时,才知道它是一个真正的promise。这个条款允许使用特定于实现的方法来采用符合规范的已知 Promise 的状态。

译者补充 : 这段话强调了在使用 Promise 时的一般性原则。

它指出了在处理 Promise 时的一个现实情况:只有当前实现的 Promise 对象能够被确定为符合规范的真正 Promise。其他来源的 Promise 对象可能会不符合规范,或者有一些了仅限于它的实现的一些方法,因此不能完全被视为符合规范。

这个条款允许在遇到符合规范的已知 Promise 对象时,使用实现特定的方式 来获取其状态。
(对于 Promise 对象,不同的 JavaScript 引擎或库可能有不同的内部实现方式,这可能导致在处理 Promise 时,一些操作在一个实现中有效,而在另一个实现中可能无效或产生不同的结果。因此,当规范中提到"使用实现特定的方式"时,它允许开发者在特定实现下,根据该实现的行为或特性,采取适当的措施来处理 Promise 对象。)
换句话说 ,它允许实现根据自身的特性和规范遵循,去利用已知符合规范的 Promise 对象,采用它们的状态以继续进行异步操作或 Promise 链式调用。
(举例来说,一些 JavaScript 引擎可能会提供特定的内置函数或方法,允许开发者直接访问或操作 Promise 对象的状态或属性。这些内置函数可能不在 Promise/A+ 规范中定义,但在特定实现下可能是有效的,并且开发者可以使用它们来采用(获取)已知符合规范的 Promise 的状态执行其他特定于该实现的操作。)

总体而言,这个条款强调了在使用 Promise 时应该考虑到来自不同实现的差异,并且在处理来自当前实现的 Promise 时,可以使用特定于该实现的方法来操作这些 Promise 对象,但是这种做法可能不适用于其他非规范兼容的 Promise 实现。

3.5

引用注释处

This procedure of first storing a reference to x.then, then testing that reference, and then calling that reference, avoids multiple accesses to the x.then property. Such precautions are important for ensuring consistency in the face of an accessor property, whose value could change between retrievals.

翻译 :首先存储x.then的引用地址,然后测试该引用,最终调用该引用,这个过程避免对x.then属性的多次访问。这些预防措施对于确保访问器属性 的一致性非常重要,因为访问器属性的值可能在每次检索之间发生变化。

译者补充 : JavaScript 对象的属性可以是数据属性 也可以是访问器属性

访问器属性的值是通过 getter 和 setter 函数进行定义和访问的。

当一个对象的属性是访问器属性时,在不同时间点访问这个属性可能得到不同的值,因为每次访问都会触发 getter 函数。因此,为了确保在处理 Promise 时的一致性和稳定性,规范建议首先将对属性的引用存储为变量,然后对该变量进行测试和使用,而不是多次直接访问属性本身。

一般只能通过Object.defineProperty对象字面量方式定义getter、setter。使其成为访问器属性。

3.6

引用注释处

Implementations should not set arbitrary limits on the depth of thenable chains, and assume that beyond that arbitrary limit the recursion will be infinite. Only true cycles should lead to a TypeError; if an infinite chain of distinct thenables is encountered, recursing forever is the correct behavior.

翻译 :实现不应该对thenable链 的深度设置任意限制,并假设在超出该任意限制后,递归将会无限进行。只有真正的循环才会导致TypeError;如果遇到一个无限的不同的thenable链,无限递归是正确的行为。

相关推荐
新中地GIS开发老师2 分钟前
25考研希望渺茫,工作 VS 二战,怎么选?
javascript·学习·考研·arcgis·地理信息科学·地信
萧大侠jdeps11 分钟前
Vue 3 与 Tauri 集成开发跨端APP
前端·javascript·vue.js·tauri
JYeontu1 小时前
实现一个动态脱敏指令,输入时候显示真实数据,展示的时候进行脱敏
前端·javascript·vue.js
发呆的薇薇°1 小时前
react里使用Day.js显示时间
前端·javascript·react.js
嘤嘤嘤1 小时前
基于大模型技术构建的 GitHub Assistant
前端·github
KeepCatch1 小时前
CSS 动画与过渡效果
前端
跑跑快跑1 小时前
React vite + less
前端·react.js·less
web136885658711 小时前
ctfshow_web入门_命令执行_web29-web39
前端
GISer_Jing1 小时前
前端面试题合集(一)——HTML/CSS/Javascript/ES6
前端·javascript·html
清岚_lxn1 小时前
es6 字符串每隔几个中间插入一个逗号
前端·javascript·算法