-
Notifications
You must be signed in to change notification settings - Fork 213
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[实践系列]Promises/A+规范 #3
Labels
Comments
cb = cb(this.value) 为啥cb执行后返回值要赋值给cb呢? |
关于你的链式调用
一个示例代码: var Deferred = function () {
var _pending = [], _result;
return {
resolve: function (result) {
_result = result;
if (_pending) {
for (var item, r, i = 0, l = _pending.length; i < l; i++) {
item = _pending[i];
r = item[1](_result);
// 如果回调的结果返回的是 promise(有then方法), 则调用 then 方法并将 resolve 方法传入
if (r && typeof r.then === 'function') {
r.then.call(r, item[0].resolve);
} else {
item[0].resolve(_result);
}
}
}
_pending = null;
},
promise: {
then: function (callback) {
// 创建一个新的 defer 并返回, 并且将 defer 和 callback 同时添加到当前的 pending 中。
var defer = Deferred();
if (_pending) {
_pending.push([defer, callback]);
} else {
callback(_result);
}
return defer.promise;
}
}
}
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
什么是Promise ?
Promises/A+ 规范
术语
解决 (fulfill) : 指一个 promise 成功时进行的一系列操作,如状态的改变、回调的执行。虽然规范中用 fulfill 来表示解决,但在后世的 promise 实现多以 resolve 来指代之。
拒绝(reject) : 指一个 promise 失败时进行的一系列操作。
拒因 (reason) : 也就是拒绝原因,指在 promise 被拒绝时传递给拒绝回调的值。
终值(eventual value) : 所谓终值,指的是 promise 被解决时传递给解决回调的值,由于 promise 有一次性的特征,因此当这个值被传递时,标志着 promise 等待态的结束,故称之终值,有时也直接简称为值(value)。
Promise : promise 是一个拥有 then 方法的对象或函数,其行为符合本规范。
thenable : 是一个定义了 then 方法的对象或函数,文中译作“拥有 then 方法”。
异常(exception) : 是使用 throw 语句抛出的一个值。
基本要求
1. Promise的状态
一个Promise的当前状态必须是以下三种状态中的一种: 等待状态(Pending) 执行状态(Fulfilled) 和 拒绝状态(Rejected)。
等待状态 (Pending)
处于等待态时,promise 需满足以下条件:
执行状态 (Fulfilled)
处于执行态时,promise 需满足以下条件:
不能迁移至其他任何状态
必须拥有一个不可变的终值
拒绝状态 (Rejected)
处于拒绝态时,promise 需满足以下条件:
不能迁移至其他任何状态
必须拥有一个不可变的据因
这里的不可变指的是恒等(即可用 === 判断相等),而不是意味着更深层次的不可变(译者注:盖指当 value 或 reason 不是基本值时,只要求其引用地址相等,但属性值可被更改)
2. Then 方法
一个 promise 必须提供一个 then 方法以访问其当前值、终值和据因。
promise 的 then 方法接受两个参数:
参数可选
onFulfilled 和 onRejected 都是可选参数。
如果 onFulfilled 不是函数,其必须被忽略
如果 onRejected 不是函数,其必须被忽略
onFulfilled 特性
如果 onFulfilled 是函数:
当 promise 执行结束后其必须被调用,其第一个参数为 promise 的终值
在 promise 执行结束前其不可被调用
其调用次数不可超过一次
onRejected 特性
如果 onRejected 是函数:
当 promise 被拒绝执行后其必须被调用,其第一个参数为 promise 的据因
在 promise 被拒绝执行前其不可被调用
其调用次数不可超过一次
调用时机
onFulfilled 和 onRejected 只有在执行环境堆栈仅包含平台代码时才可被调用 注1
注1 这里的平台代码指的是引擎、环境以及 promise 的实施代码。实践中要确保 onFulfilled 和 onRejected 方法异步执行,且应该在 then 方法被调用的那一轮事件循环之后的新执行栈中执行。
这个事件队列可以采用“宏任务(macro - task)”机制或者“微任务(micro - task)”机制来实现。
由于 promise 的实施代码本身就是平台代码(译者注:即都是 JavaScript),故代码自身在处理在处理程序时可能已经包含一个任务调度队列。
调用要求
onFulfilled 和 onRejected 必须被作为函数调用(即没有 this 值)
多次调用
then 方法可以被同一个 promise 调用多次
当 promise 成功执行时,所有 onFulfilled 需按照其注册顺序依次回调
当 promise 被拒绝执行时,所有的 onRejected 需按照其注册顺序依次回调
简易版实践
首先
package.json
simple.js
就这样,一个简单的promise就完成了.
接下来,我们来看看我们的实现是否完全符合promises/A+规范~
GG,测试用例只过了一小部分,大部分飘红~
OK,接下来,我们来继续了解promises/A+ 进一步的规范要求~
进一步要求
由于接下来的要求比较抽象和难理解,所以我们将一步一步实践来加深理解。
1. 返回
1.then方法必须返回一个promise对象
2.如果 onFulfilled 或者 onRejected 返回一个值 x ,则运行下面的 Promise 解决过程:[[Resolve]](promise2, x)
3.如果 onFulfilled 或者 onRejected 抛出一个异常 e ,则 promise2 必须拒绝执行,并返回拒因 e。
4.如果 onFulfilled 不是函数且 promise1 成功执行, promise2 必须成功执行并返回相同的值。
5.如果 onRejected 不是函数且 promise1 拒绝执行, promise2 必须拒绝执行并返回相同的据因。
6.不论 promise1 被 reject 还是被 resolve 时 promise2 都会被 resolve,只有出现异常时才会被 rejected。
我们通过以上要求来一步一步完善then方法
1.
4,5.
ok,完整的then方法搞定了。相信通过以上实践,你对返回要求已经有了更深的理解。
2. Promise 解决过程
运行 [[Resolve]](promise, x) 需遵循以下步骤:
1。x 与 promise 相等
如果 promise 和 x 指向同一对象,以 TypeError 为据因拒绝执行 promise。
2。x 为 Promise
如果 x 为 Promise ,则使 promise 接受 x 的状态。
如果 x 处于等待态, promise 需保持为等待态直至 x 被执行或拒绝。
如果 x 处于执行态,用相同的值执行 promise。
如果 x 处于拒绝态,用相同的据因拒绝 promise。
3。x 为对象或函数
如果 x 为对象或者函数:
把 x.then 赋值给 then。
如果取 x.then 的值时抛出错误 e ,则以 e 为据因拒绝 promise。
如果 then 是函数,将 x 作为函数的作用域 this 调用之。传递两个回调函数作为参数,第一个参数叫做 resolvePromise ,第二个参数叫做 rejectPromise:
如果 x 不为对象或者函数,以 x 为参数执行 promise
如果一个 promise 被一个循环的 thenable 链中的对象解决,而 [[Resolve]](promise, thenable) 的递归性质又使得其被再次调用,根据上述的算法将会陷入无限递归之中。算法虽不强制要求,但也鼓励施者检测这样的递归是否存在,若检测到存在则以一个可识别的 TypeError 为据因来拒绝 promise 。
1.x 与 promise 相等
2.x 为 Promise。
3.x 为对象或函数
Ok~比较复杂的解决过程也让我们搞定了.接下来我们整合下代码
Promises/A+ 规范 实践
再来看看我们的实现是否符合Promises/A+规范
nice,测试用例全部通过!
参考文献
Promises/A+规范译文
Promise详解与实现
The text was updated successfully, but these errors were encountered: