Promise/A+ 规范 - 中文版本
Promises/A+
这是一个开放标准,旨在让不同开发者实现的 JavaScript Promise 能够无缝衔接并应用——由前辈们制定,为其他后来者提供参考
一个 promise 所表示的是异步操作的结果。与 promise 交互的主要方式是通过它的 then 方法,该方法会注册所传入的回调函数,回调函数将接收 promise 的最终值或者 promise 无法被满足时的原因。
本规范详细说明了 then 方法的行为,为所有符合 Promises/A+ 标准的 promise 实现提供可靠的基础。因此本规范的更新或修订应被视为非常稳定。虽然 Promises/A+ 组织可能会偶尔对本规范进行向后兼容的小幅度修订,以解决新发现的边缘情况,但我们依然会在经过认真仔细的考虑、讨论和测试后,才会去整合重大或者不向后兼容的变更。
在过去,Promises/A+ 不仅明确早期 Promise/A 提案中的涉及的行为条款,而且还扩展了一些涵盖实际行为的内容,并且省略了那些不清不楚或存在问题的部分。
最后要说的是,Promises/A+ 规范的核心并不涉及如何创建、满足或拒绝 promise,而是选择专注于提供一个强大的 then 方法以确保不同实现之间的兼容性。大概未来的相关规范才可能会涉及如何创建、满足和拒绝 promise 这些主题吧。
1 专业术语
thenable: 一个具有then方法的对象或函数。promise:一个具有then方法的对象或函数,then方法的行为符合本规范。value:是一个合法的 JS 值,含undefined、null、thenable或promise等。exception:通过throw语句抛出的值。reason:通常用于表示promise被拒绝/无法实现的原因,也是个值。
2 详细规范
2.1 Promise 状态
一个 promise 必须处于以下三种状态之一:
待定中(pending)、已实现(fulfilled)、已拒绝(rejected)
关于这些状态的描述如下:
- 待定中 —— pending:
- 可以转变为其它两种状态,也就是已实现(fulfilled)或已拒绝(rejected)
- 已实现 —— fulfilled:
- 禁止从该状态转变为其它状态,状态不可改变
- 必须有一个不可改变的值(value —— 完成后的成果!!)
- 已拒绝 —— rejected:
- 禁止从该状态转变为其它状态,状态不可改变
- 必须有一个不可改变的原因(reason —— 为什么拒绝!?)
注意:
不可改变并不意味着深层次的不可变(比如属性描述符中writeable: false),你可以通过对当前状态进行全等判断(===),从而更改相应的值/原因和状态后,那么不可改变自然而然的就会成立了。
2.2 then 方法
一个 promise 必须提供一个 then 方法,它可以访问当前或最终的值或者原因。
promise 的 then 方法接受两个参数:
promise.then(onFulfilled, onRejected)
onFulfilled和onRejected均是可选参数:- 如果
onFulfilled不是一个函数,则必须被忽略。 - 如果
onRejected不是一个函数,则必须被忽略。
被忽略是指我们不对它做任何的处理,不会抛出任何的错误- 如果
如果
onFulfilled是一个函数:- 必须在
promise被实现后调用,且以promise的值(value)作为第一个参数。 - 在
promise被实现之前不可调用。 - 不允许被多次调用。
- 必须在
如果
onRejected是一个函数:- 必须在
promise被拒绝后调用,且以promise的原因(reason)作为第一个参数。 - 在
promise被拒绝之前不可调用。 - 不允许被多次调用。
- 必须在
onFulfilled或onRejected必须在执行上下文栈仅包含平台代码时才被调用。[[3.1](#3 引注)]onFulfilled和onRejected必须作为函数调用(没有this值)。[[3.2](#3 引注)]then可以在同一个 promise 上被多次调用。- 当
promise被实现时,所有相应的onFulfilled回调必须按它们调用then的顺序执行。 - 当
promise被拒绝时,所有相应的onRejected回调必须按它们调用then的顺序执行。
- 当
then必须返回一个 promise [[3.3](#3 引注)]。promise2 = promise1.then(onFulfilled, onRejected);
- 如果
onFulfilled或onRejected返回一个值x,则运行 Promise 解决过程[[Resolve]](promise2, x)[[2.3](#2.3 Promise 解决过程)]。 - 如果
onFulfilled或onRejected抛出异常e,则promise2必须以e作为原因被拒绝。 - 如果
promise1被实现且onFulfilled不是一个函数,那么promise2必须以与promise1相同的值(value)被实现。 - 如果
promise1被拒绝且onRejected不是一个函数,那么promise2必须以与promise1相同的原因(reason)被拒绝。
- 如果
2.3 Promise 解决过程
Promise 解决过程 是一种抽象操作,它接受一个 promise 和一个值作为输入,表示为 [[Resolve]](promise, x)。如果 x 是一个 thenable,则会尝试使 promise 采用 x 的状态,前提是 x 至少在某种程度上表现得像一个 promise。否则,它将用值 x 来实现 promise。
对 thenable 的这种处理方式使得不同的 promise 实现能够有效兼容,只要它们提供符合 Promises/A+ 标准的 then 方法。但是也允许 Promises/A+ 实现能够“接纳”那些具有合理 then 方法的非标准实现。
要实现 [[Resolve]](promise, x),请按照以下步骤操作:
- 如果
promise和x指向同一个对象,则以TypeError拒绝promise作为原因。 - 如果
x是一个 promise,则采用其状态 [[3.4](#3 引注)]:- 如果
x是待定状态,promise必须保持待定,直到x被实现或拒绝。 - 如果
x被实现,使用相同的值实现promise。 - 如果
x被拒绝,使用相同的原因拒绝promise。
- 如果
- 否则,如果
x是一个对象或函数:- 将
then设置为x.then。[[3.5](#3 引注)] - 如果检索属性
x.then时抛出异常e,则以e作为原因拒绝promise。 - 如果
then是一个函数,则以x作为this调用它,第一个参数为resolvePromise,第二个参数为rejectPromise,其中:- 如果
resolvePromise被调用并传入值y,则运行[[Resolve]](promise, y)。 - 如果
rejectPromise被调用并传入原因r,则以r拒绝promise。 - 如果同时调用了
resolvePromise和rejectPromise,或对同一参数进行了多次调用,第一次调用优先,后续调用将被忽略。 - 如果调用
then时抛出异常e,- 如果
resolvePromise或rejectPromise已被调用,则忽略该异常。 - 否则,以
e作为原因拒绝promise。
- 如果
- 如果
- 如果
then不是一个函数,则用x来实现promise。
- 将
- 如果
x既不是对象也不是函数,则用x来实现promise。
如果一个 promise 被一个循环的 thenable 链中的对象解决,而 [[Resolve]](promise, thenable) 的递归性质使得它被再次调用,按照上述算法将会导致无限递归。虽然算法并不强制要求检测这种递归,但我们鼓励实现者可以这样做。如果检测到存在循环,则应以一个语义清晰的 TypeError 拒绝 promise。[[3.6](#3 引注)]
3 引注
这里的“平台代码”指的是引擎、环境和 promise 的实现代码。实际上,这一要求确保
onFulfilled和onRejected在调用then的事件循环转之后异步执行,并且在一个新的调用栈中。这可以通过“宏任务”机制(如setTimeout或setImmediate)或“微任务”机制(如MutationObserver或process.nextTick)来实现。由于 promise 实现被视为平台代码,它本身可能包含一个任务调度队列或“跳板”,用于调用处理程序。也就是说,在严格模式下,
this的值将是undefined;在非严格模式下,this将指向全局对象。实现可以允许
promise2 === promise1,前提是该实现满足所有要求。每个实现应记录是否可以产生promise2 === promise1以及在什么条件下可以实现。通常,只有当
x来自当前实现时,才能确定x是一个真正的 promise。这一条款允许使用特定于实现的方法来采用已知符合标准的 promises 的状态。这个过程首先存储对
x.then的引用,然后测试该引用,最后调用该引用,避免了对x.then属性的多次访问。这种预防措施对于确保在访问器属性的情况下保持一致性非常重要,因为该属性的值可能在多次检索之间发生变化。实现不应对 thenable 链的深度设置任意限制,并假设超出该限制的递归将是无限的。只有真正的循环才应导致
TypeError;如果遇到无限的不同 thenable 链,则无限递归是正确的行为。
Promise/A+ 规范 - 中文版本的更多相关文章
- Promise A+ 规范【中文版】
0. 前言 本文为Promise A+规范的中文译文,Promise A+规范英文版原文链接:Promise A+. 正文如下: 一个开放.健全且通用的 JavaScript Promise 标准.由 ...
- 按照 Promise/A+ 规范逐行注释并实现 Promise
0. 前言 面试官:「你写个 Promise 吧.」 我:「对不起,打扰了,再见!」 现在前端越来越卷,不会手写 Promise 都不好意思面试了(手动狗头.jpg).虽然没多少人会在业务中用自己实现 ...
- Angularjs中文版本开发指南发布
从本人开始在写关于Angularjs的文章开始,也算是见证了Angularjs在国内慢慢的火起来,如今的Angularjs正式如日中天.想知道为什么Angularjs会这么火,请移步angularjs ...
- Promise A 规范的一个简单的浏览器端实现
简单的实现了一个promise 的规范,留着接下来模块使用.感觉还有很多能优化的地方,有时间看看源码,或者其他大神的代码 主要是Then 函数.回调有点绕人. !(function(win) { fu ...
- 【javascript】Promise/A+ 规范简单实现 异步流程控制思想
——基于es6:Promise/A+ 规范简单实现 异步流程控制思想 前言: nodejs强大的异步处理能力使得它在服务器端大放异彩,基于它的应用不断的增加,但是异步随之带来的嵌套.难以理解的代码让 ...
- Promise原理讲解 && 实现一个Promise对象 (遵循Promise/A+规范)
1.什么是Promise? Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一 2.对于几种常见异步编程方案 回调函数 事件监听 发布/ ...
- 如何在FreePBX ISO 中文版本安装讯时网关,潮流16FXS 网关和潮流话机
如何在FreePBX ISO 中文版本安装讯时网关,潮流16FXS 网关和潮流话机摘自:http://www.siplab.cn/?p=664 1)迅时的fxo口网关要注册到asterisk,所以现在 ...
- 手写一款符合Promise/A+规范的Promise
手写一款符合Promise/A+规范的Promise 长篇预警!有点长,可以选择性观看.如果对Promise源码不是很清楚,还是推荐从头看,相信你认真从头看到尾,并且去实际操作了,肯定会有收获的.主要 ...
- when 让你跳出异步回调噩梦 node.js下promise/A规范的使用
其实关于promise 的博客,前端时间专门写了一篇关于 promise 规范的文章,promise规范 让 javascript 中的异步调用更加人性化. 简单回忆下: promise/A规范定义的 ...
- Promise/A+规范
1.什么是Promise? Promise是JS异步编程中的重要概念,异步抽象处理对象,是目前比较流行Javascript异步编程解决方案之一 2.对于几种常见异步编程方案 回调函数 事件监听 发布/ ...
随机推荐
- 我们在 vue 项目中如何做路由导航守卫
一般在 src 文件夹新建一个 permission 文件 ,单独用来做路由导航守卫业务 ,在 main.js 导入文件即可 : 主要功能有 判断是否有 token ,以此判断用户是不是登录了 :
- 洛谷P1219八皇后问题
[USACO1.5] 八皇后 Checker Challenge 题目链接 题目描述 一个如下的 \(6 \times 6\) 的跳棋棋盘,有六个棋子被放置在棋盘上,使得每行.每列有且只有一个,每条对 ...
- 多平台文章同步浏览器插件 – ArticleSync
ArticleSync - 多平台文章同步插件 ArticleSync 是一个浏览器扩展,帮助用户轻松将文章同步发布到多个社交平台.支持将文章从本地草稿发布到各大平台,如知乎.Bilibili 等.它 ...
- 云原生周刊:目前的 Kubernetes 开源监控方案有没有缺陷?
视频推荐 目前的 Kubernetes 开源监控方案有没有缺陷? YouTube 频道 OpenObservability Talks 最新一期视频邀请了 VictoriaMetrics 项目的创始人 ...
- PBA 商业分析师 考试心得
2021年7月报名开始学习PBA,因为疫情,中间经历两次考试延期,虽然复习时间增多了,但是学习的节奏也被打乱.好在没有白努力,今天收到了邮件,5A通过考试.在这里整理学习经验,梳理一下自己的思路,也希 ...
- Linux利用scp命令上传下载文件
scp是secure copy的简写,用于在 Linux 下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器. scp传输是加密的,可能会稍微影响一下速度.当你服务 ...
- 需求解决 _针对特定Class设置样式 _CSS _20210906
需求解决 _针对特定Class设置样式 _CSS _20210906 有一个需求,需要对一些具有 某个Class的标签 ,icon,以及其中的字体设置 隐藏或者展示 解决方法如下:(需要对 该页面引用 ...
- PHP word PDF excel 文档互转 预览 (linux libreoffice)
1--卸载系统当前的libreoffice 执行如下命令:yum remove libreoffice-* 2--为了能使用镜像,在etc 目录之下的hosts文件内加入代理. 注意没有加的话,可能 ...
- 2024-11-13:求出所有子序列的能量和。用go语言,给定一个整数数组nums和一个正整数k, 定义一个子序列的能量为子序列中任意两个元素之间的差值绝对值的最小值。 找出nums中长度为k的所有子
2024-11-13:求出所有子序列的能量和.用go语言,给定一个整数数组nums和一个正整数k, 定义一个子序列的能量为子序列中任意两个元素之间的差值绝对值的最小值. 找出nums中长度为k的所有子 ...
- 鸿蒙NEXT开发案例:年龄计算
[引言] 本案例的目标是开发一款年龄计算器应用,该应用能够根据用户输入的出生日期,计算出用户的实际年龄.虚岁.星座.生肖等信息.同时,应用还将提供距离下次公历和农历生日的天数及星期等信息.为了实现 ...