美文网首页
「翻译练习」Promises/A+

「翻译练习」Promises/A+

作者: 这名字真不对 | 来源:发表于2019-04-09 16:27 被阅读0次

    一个由开发者为开发者提供的健全、互操作(interoperable)的JavaScript Promise 标准

    互操作性指一种不同系统或组织之间可以协同工作的能力。在这里可以理解为只要符合该标准的的Promise实现,在语法上能够相互调用。

    promise表示异步操作的最终结果。then方法是promise主要的交互方法,它通过注册回调函数,接收promise的最终结果或promise不能被履行(fulfilled)的原因。

    这份文档详细说明了then方法的行为,提供了可互操作的基础,所有符合Promises/A+规范的都可以以这份标准实现。因此,这份标准非常稳定。尽管Promises/A+组织可能偶尔为了解决新发现的极端情况修改该规范,进行细微的修改,并向后兼容,我们会经过仔细考虑讨论和测试,才会整合较大的更改或向后不兼容的变更。

    从过去的历史来看,Promises/A+解释了Promise/A 提案的早期的条款,并拓展了它,以解决早期不清楚的、有问题的部分。

    最后,Promises/A+规范的核心没有涉及如何构建,履行(fufill),拒绝(reject)承诺,而是专注于提供可互操作的then方法。未来,关于规范的工作可能会涉及这些部分。

    1. 术语

    1.1. "promise" 是一个有符合该规范then方法的对象(object)或函数(function)。
    1.2. "thenable" 是一个定义then方法的对象(object)或函数(function)。
    1.3. "value" 是一个合法的JavaScript值 (包含undefined,thenablepromise)。
    1.4. "exception" 是使用throw语句抛出的值。
    1.5. "reason" 是一个包含promise为何被拒绝原因的值。

    2. 要求

    2.1 Promise 状态

    一个promise必须处于三种状态之一:pending,fulfilled,rejected

    2.1.1 当pending时,promise:

    • 2.1.1.1 可以转换成fufilledrejected状态

    2.1.2 当fulfilled时,promise:

    • 2.1.2.1 不能转换成其他任何状态
    • 2.1.2.2 必须有value,值不能改变

    2.1.3 当rejected时,promise:

    • 2.1.3.1 不能转换成其他任何状态
    • 2.1.3.2 必须有reasonreason不可改变

    这里的不可改变指的是(比如两个值===),但不意味着深度不可变(比如const声明下的对象)。

    2.2 then 方法

    一个promise必须提供then方法用于接受当前或最终的值或原因。
    一个promisethen方法接受两个参数:

    promise.then(onFufilled, onRejected)
    

    2.2.1 onFufilledonRejected都为可选参数
    2.2.1.1 如果onFufilled不是函数,必须被忽略
    2.2.1.2 如果onRejected不是函数,必须被忽略

    2.2.2 如果onFufilled是一个函数

    • 2.2.2.1 当promise状态变更为fufilled时,必须被调用,且promise的值作为其第一个参数
    • 2.2.2.2 当状态已经是fufilled时,不能再被调用
    • 2.2.2.3 不能调用超过1次

    2.2.3 如果onRejected是一个函数

    • 2.2.2.1 当promise状态变更为onRejected时,必须被调用,且promise的原因作为其第一个参数
    • 2.2.2.2 当状态已经是rejected时,不能再被调用
    • 2.2.2.3 不能调用超过1次

    2.2.4 onFufilledonRejected 在执行环境堆栈只包含平台代码之前不得调用[3.1]

    2.2.5 onFufilledonRejected 必须为函数形式调用,比如默认情况下函数调用时this值为undifined(比如fnc();)

    2.2.6 then在同一个promise内可以调用多次

    • 2.2.6.1 当promise状态变更为fufilled时,所有onFufilled回调必须按then方法注册时的顺序依次执行
    • 2.2.6.2 当promise状态变更为rejected时,所有onRejected回调必须按then方法注册时的顺序依次执行

    2.2.7 then 方法必须返回一个promise[3.3]
    promise2 = promise1.then(onFufilled, onRejected)

    • 2.2.7.1 如果onFulfilledonRejected返回一个值(value)x,那么执行[[Resolve]](promise2, x)
    • 2.2.7.2 如果onFulfilledonRejected抛出一个异常e,那么promise2必须使用e作为拒绝原因(promise2捕获e异常)
    • 2.2.7.3 如果onFulfilled不是一个函数,且promise1状态变为fufilledpromise2一定会接收promise1变更为fulfilled时相同的值(value)
    • 2.2.7.4 如果onRejected不是一个函数,且promise1状态变为rejectedpromise2一定会接收promise1变更为rejected时相同的原因(reason)

    2.3 Promise Resolution Procedure(PRP)

    PRP是一个抽象的操作,以一个promise和值(value)作为参数输入,表示为[[Resolve]](promise, x)。如果xthenable对象,假设x的行为和promise对象有一点相似,尝试让promise处理x的状态。否则,x作为值履行(fulfills)promise

    这种处理thenables的方式使得各种promise的实现可以互通,只要它们开放出一个与Promise/A+协议兼容的 then 方法即可。。它也允许Promises/A+的实现"接守"(原文"assimilate",吸收)那些不符合规范但合理的then方法。

    [[Resolve]](promise, x),表现为以下步骤(以下的promise,x):
    备注:下面的promise x分别表示这里的两个值

    2.3.1 如果promisex引用同一个对象(循环引用),使用TypeError作为理由拒绝promise

    2.3.2 如果x是一个promise实例,使用它的状态[3.4]:

    • 2.3.2.1 如果xpending状态,则promise需要保持pending只到x状态变更为fufilled或者rejected
    • 2.3.2.2 如果x的状态变更为fulfilled,使用相同的value fufill promise
    • 2.3.2.3 如果x的状态变更为rejected,使用相同的reason rejectpromise

    2.3.3 其他情况,如果x是一个对象或者函数:

    • 2.3.3.1 x.then赋值给then[3.5]
    • 2.3.3.2 如果访问x.then会抛出异常e,那么使用e作为理由rejectpromise
    • 2.3.3.3 如果then方法是函数,将x作为this,并以resolvePromise作为第一个参数,rejectPromise作为第二个参数
      • 2.3.3.3.1 如果resolvePromise以值y调用,执行[[Resolve]](promise, y)
      • 2.3.3.3.2 如果rejectPromise以原因r调用,拒绝使用r拒绝promise
      • 2.3.3.3.3 如果resolvePromiserejectPromise都被调用,或者被使用相同的参数调用了多次,则首次调用将被优先采用,其它调用将被忽略。
      • 2.3.3.3.4 如果如果调用then方法过程中抛出异常 e:
        • 2.3.3.3.4.1 如果resolvePromiserejectPromise 都已经被调用,则忽略该异常
        • 2.3.3.3.4.2 否则使用e reject promise
    • 2.3.3.4 如果then不是函数,以x为值 fulfill promise

    2.3.4 如果x不是对象或函数,以x为值 fulfill promise

    如果一个promise对象被一个处于循环thenable链中的thenable对象解决(resolve),由于 [[Resolve]](promise, thenable)的递归本质会使得其再次被调用,按照上面的算法,这种情况将导致无限递归。本规范鼓励实现检测这种递归情况的出现,并使用带有一定信息的 TypeError 作为原因拒绝执行 promise [3.6],但规范不对此检测做强制要求。

    3. 备注

    3.1 这里“平台代码”指的是引擎(engine)、环境(environment)以及 promise 的实现代码(implementation code)。实际上,这个要求确保了onFulfilledonRejected方法能够异步执行,即在调用then方法的那个事件循环之后的新执行栈中异步执行。这个要求可以通过“宏任务(macro-task)”机制(例如 setTimeout 或者 setImmediate)或者“微任务(micro-task)”(例如MutationObserver或者process.nextTick)来实现。由于promise的实现本身也被认为是“平台代码”,所以其自身可能也会包含一种任务调度队列或者“trampoline”控制结构来对其处理程序进行调用。

    3.2 也就是说,this的值,在严格模式(strict)下为undefined;在非严格模式下为全局对象(global object)。

    3.3 在满足所有要求的情况下,实现中可能允许promise2 === promise1。每个实现都需要说明其是否允许出现promise2 === promise1,以及在何种条件下出现。

    3.4 通常来说,只有当x是从当前实现中定义出来的,我们才知道它是否是一个真正的promise对象。这条规则允许使用特定实现中的方法去采用符合规范的promise对象的状态。

    3.5 这一步中先会存储一个指向x.then的引用,然后测试该调用,之后调用该引用,避免对x.then属性的多处访问。这些预防措施对于保证访问器属性的一致性至关重要,因为其值可能在多次取值期间发生变化。

    3.6 实现不应该限定thenable链的深度,并假设只要超出了限制,递归就是无限的。只有真正的循环递归才应导致一个TypeError错误;如果一条无限长链上的thenable对象各不相同,那么无限递归下去就是正确的行为。

    相关文章

      网友评论

          本文标题:「翻译练习」Promises/A+

          本文链接:https://www.haomeiwen.com/subject/mjxmiqtx.html