十五的学习日记20161004
JavaScript
promise/A+标准
-
术语
- 1.1
promise
是一种object
或function
,带有一个方法名叫then
,这个方法的行为遵照本标准设定. - 1.2
thenable
意味着一个object
或function
定义了then
方法. - 1.3
value
是任何合法的JavaScript 值(包括undefined
,thenable
或者promise
) - 1.4
exception
是一个通过throw
声明抛出的值. - 1.5
reason
是一个解释为什么一个promise
被拒绝的词.
- 1.1
-
要求
-
2.1
promise
的状态:
一个promise
必须在三个状态中:pending,fulfilled,rejected
.- 2.1.1 当一个 promise处于
pending
状态时:- 2.1.1.1 有可能转变到
fulfilled
或rejected
状态.
- 2.1.1.1 有可能转变到
- 2.1.2 当一个 promise处于
fulfilled
状态时:- 2.1.2.1 不能再转变到其他状态.
- 2.1.2.2 必须要有一个不变的
value
.
- 2.1.3 当一个 promise处于
rejected
状态时:- 2.1.3.1 不能再转变到其他状态
- 2.1.3.2 必须要一个不变的
reason
.
- 2.1.1 当一个 promise处于
-
2.2
then
方法:
一个promise
必须提供一个then
方法, 以用来传递他当前或最终的value
或reason
一个promise
的then
方法接受两个参数:
promise.then(onFulfilled,onRejected)
- 2.2.1
onFulfilled,onRejected
两者都是可选参数, 如果参数不为function
类型,必须被忽略. - 2.2.2 如果
onFulfilled
是一个function
:- 2.2.2.1 它必须在
promise
成为fulfilled
状态后被调用,并且将promise
的value
作为其第一个参数传入.//想问参数在哪里?resolve(arg)
传入参数 - 2.2.2.2 它不能在
promise
成为fulfilled
状态前被调用. - 2.2.2.3 它不能被调用超过一次.
- 2.2.2.1 它必须在
- 2.2.3 如果
onRejected
是一个function
:- 2.2.3.1 它必须在
promise
成为onRejected
状态后被调用,并且将promise
的reason
作为其第一个参数传入.//想问参数在哪里?resolve(arg)
传入参数 - 2.2.3.2 它不能在
promise
成为onRejected
状态前被调用. - 2.2.3.3 它不能被调用超过一次.
- 2.2.3.1 它必须在
- 2.2.4 在执行上下文栈(
execution context stack
)中只剩下平台代码前onFulfilled
或onRejected
都不能被调用.
//下面把完成与失败简写做yes和no. - 2.2.5
yes
或no
必须以函数来调用(也就是没有this 的值). - 2.2.6 在同一个
promise
上then
可以被多次调用.- 2.2.6.1 当且仅当
promise
是yes
时, 所有的onyes
回调必须各自按他们then
最原初的顺序执行. - 2.2.6.2 当且仅当
promise
是no
时, 所有的onno
回调必须各自按他们then
最原初的顺序执行.
- 2.2.6.1 当且仅当
- 2.2.7
then
必须返回一个promise
; - 例如:
promise2 = promise1.then(onyes,onno);
- 2.2.7.1 不管是
onyes
或onno
返回了一个值x, 执行Promise Resolution Procedure
(promise 解决程序)[[Resolve]](promise2, x)
. - 2.2.7.2 不管是
onyes
或onno
抛出了一个异常e ,promise2
必须获取值e作为no
的reason
- 2.2.7.3 如果
onyes
不是一个函数,而 promise1完成了yes
状态,promise2
必须以yes
状态接受promise1
的值. - 2.2.7.4 如果
onno
不是一个函数,而 promise1完成了no
状态,promise2
必须以no
状态接受promise1
的值.
- 2.2.7.1 不管是
- 2.2.1
-
2.3 Promise 解决过程
-
promise 解决过程是一个以输入promise输出value的抽象操作,我们将此标记为:
[[Resolve]](promise,x)
.如果x 是一个thenable
, 那么会尝试尽量让promise
接受x的状态, 假设x的表现会像一个promise
.否则 那会让promise
转为yes
状态. -
这种处理允许
promise
的实现互操作,只要他们暴露的接口符合Promises/A+的then
规范.也同时让Promises/A+以可理解的方式实现then方法. -
为了运转
[[Resolve]](promise,x)
,须按照如下规则实现:-
2.3.1 如果
promise
和x
指向了同一个对象,promise
转为no
并带着一个类型错误作为理由. -
2.3.2 如果
x
是一个promise
那么调整他的状态:- 2.3.2.1 如果
x
处于pending
,promise
必须保持pending
直到x
转为yes
或no
. - 2.3.2.2 如果
x
转到了yes
,promise
也应该yes
并带上同样的value. - 2.3.2.3 如果
x
转到了no
,promise
也应该no
并带上同样的reason.
- 2.3.2.1 如果
-
2.3.3 其他情况,如果
x
是一个对象或函数.- 2.3.3.1 让
then
转为x.then
. - 2.3.3.2 如果属性
x.then
取回时抛出异常e,promise
转换为no
以e 作为 reason. - 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,转变promise
为no
带着理由r. - 2.3.3.3.3 如果
resolvePromise
和rejectPromise
都被调用了,或多重调用到了同一个参数,第一个调用被保留,其他的调用忽略. - 2.3.3.3.4 如果 调用的
then
抛出一个异常e.- 2.3.3.3.4.1 如果
resolvePromise
或rejectPromise
已经被调用了, 忽略这个异常. - 2.3.3.3.4.2 否则,
promise
转为no
带着理由e.
- 2.3.3.3.4.1 如果
- 2.3.3.3.1 如果
- 2.3.3.4 如果
then
不是一个函数,promise
转为yes
,带着值x.
- 2.3.3.1 让
-
2.3.4 如果x不是一个对象或函数,
promise
转为yes
带着值x.
如果一个promise
转为了yes
,带着一个进入了thenable
构成的循环链的then
,以至于递归地导致[[Resolve]](promise, thenable)
重复无限地被调用.实现是鼓励的,但是并没有必要,可以用一个非正式的类型异常结束.
-
-
3注意
- 3.1 这里的"平台代码"意味着引擎,环境,和promise实现代码. 实际上, 这个需求保证了
onyes
和onno
可以异步地执行, 在事件循环轮到了一个then
后,带着一个空的栈.这可以被实现为一个宏任务机制,比如setTimeout
或者setImmediate, 或者一个微任务机制,比如MutationObserver
或process.nextTick
.这promise实现被认为是平台代码, 他们可能自身包含一个任务规划队列,或在某个handlers中被调用. - 3.2 在严格模式中,this会指向undefined,而在宽松模式中,他指向全局对象.
- 3.3 具体实现可能会允许
promise2 === promise1
, 假设这两个promise的需求完全一致.每个具体实现必须在文档中指明是否会出现这样的情况,以及在何时出现. - 3.4 通常而言, ....
- 3.5 第一次储存
x.then
的步骤... - 3.6 允许封闭环递归.
- 3.1 这里的"平台代码"意味着引擎,环境,和promise实现代码. 实际上, 这个需求保证了
-