前言
最後來看一下 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 物件來實現的,沒有新的知識點。看起來不好實現的程式碼,卻是這樣幾行程式碼就實現了,是我想複雜了。
不經感慨,芸芸眾生,活到老,學到老啊。