前言
最后来看一下 Promise 的几个常用的静态方法的实现:
- Promise.resolve
- Promise.reject
- Promise.all
- Promise.race
注:本次阅读的是 then/promise 的 4.0.0 版本,源码请戳 这里。
解读
在 4.0.0 版本之中,Promise 对象被封装在了 core.js
文件中,常用的静态方法则写在了 index.js
文件中,打开 index.js 文件。
Promise.resolve
Promise.resolve 方法有下面三种使用形式:
Promise.resolve(value);
Promise.resolve(promise);
Promise.resolve(theanable);
这三种形式都会产生一个新的 Proimse,从而能够继续 then 链式调用。
Promise.resolve = function (value) {
return new Promise(function (resolve) {
resolve(value);
});
}
Promise.resolve 的实现,就是 new 一个新的 Promise 实例并调用 resolve 方法,最后返回。
Promise.reject
Promise.reject 与 Promise.resolve 同理,只不过将 resolve 替换成 reject。
Promise.reject = function (value) {
return new Promise(function (resolve, reject) {
reject(value);
});
}
Promise.all
Promise.all 可以将传入的多个 Promise 实例里都 resolve 成功再返回一个结果数组。
实现的思路就是用一个计数器,从零开始计,每当一个 Promise 实例调用了 resolve,则 +1。知道计数器等于 Promise 实例的数量时,表示全部都执行完了,此时返回结果。
Promise.all = function () {
var args = Array.prototype.slice.call(arguments.length === 1 && Array.isArray(arguments[0]) ? arguments[0] : arguments)
return new Promise(function (resolve, reject) {
if (args.length === 0) return resolve([])
var remaining = args.length
function res(i, val) {
try {
if (val && (typeof val === 'object' || typeof val === 'function')) {
var then = val.then
if (typeof then === 'function') {
then.call(val, function (val) { res(i, val) }, reject)
return
}
}
args[i] = val
if (--remaining === 0) {
resolve(args);
}
} catch (ex) {
reject(ex)
}
}
for (var i = 0; i < args.length; i++) {
res(i, args[i])
}
})
}
实现的代码里是做减法,跟计数器做加法思路是一致的。代码里 new 了一个新的 Promise,当触发了计数器设定的值(即 0),则调用它的 resolve,从而触发 then 函数。
res 函数里,给每一个 Promise 实例绑定一个 then 方法,当触发 resolve,即触发 then,从而再次调用 res 函数。只有传入的值不再是 Promise 实例,此时就用 args
记录,作为以后返回的结果数组。并重新设置计数器 remaining
(做减法)。
当 remaining
被减到了 0,表示所有传入的 Promise 实例都执行了 resolve,此时可以调用新 new 出来的 Promise 实例的 resolve 。
Promise.race
Promise.race 与 Promise.all 相反,只要传入的多个 Promise 实例只要有一个调用了 resolve 就会触发它的 then 函数。
源码是这样的:
Promise.race = function (values) {
return new Promise(function (resolve, reject) {
values.map(function(value){
Promise.cast(value).then(resolve, reject);
})
});
}
代码里也 new 了一个新的 Promise 实例,给传入的每一个 Promise 实例也都绑定 then 方法。只要有一个 Promise 执行了 then,就直接执行了 resolve。
这里的 Promise.cast 方法是为了返回一个可以调用 then 的 Promise 实例。
这里可以看最新的 源码实现 更好理解:
Promise.race = function (values) {
return new Promise(function (resolve, reject) {
values.forEach(function(value){
Promise.resolve(value).then(resolve, reject);
});
});
};
最后
看了 Promise 的静态方法源码,会发现都是基于之前的一整套 Promise 对象来实现的,没有新的知识点。看起来不好实现的代码,却是这样几行代码就实现了,是我想复杂了。
不经感慨,芸芸众生,活到老,学到老啊。