關(guān)于Promise基本方法的簡(jiǎn)單實(shí)現(xiàn)
前言
Promise 是前端面試和工作中極其常見的一個(gè)概念,關(guān)于它各種方法的手寫實(shí)現(xiàn)也很有市場(chǎng),今天在這里總結(jié)一下 Promise 基本方法的簡(jiǎn)單實(shí)現(xiàn)。
catch() 方法
catch 方法是對(duì) then 方法的封裝,只用于接收 reject(reason) 中的錯(cuò)誤信息。
因?yàn)樵?then 方法中 onRejected 參數(shù)是可不傳的,不傳的情況下,錯(cuò)誤信息會(huì)依次往后傳遞,直到有 onRejected 函數(shù)接收為止,因此在寫 promise 鏈?zhǔn)秸{(diào)用的時(shí)候, then 方法不傳 onRejected 函數(shù),只需要在最末尾加一個(gè) catch() 就可以了,這樣在該鏈條中的 promise 發(fā)生的錯(cuò)誤都會(huì)被最后的 catch 捕獲到。
catch(onRejected) { return this.then(null, onRejected); }
done() 方法
catch 在 promise 鏈?zhǔn)秸{(diào)用的末尾調(diào)用,用于捕獲鏈條中的錯(cuò)誤信息,但是 catch 方法內(nèi)部也可能出現(xiàn)錯(cuò)誤,所以有些 promise 實(shí)現(xiàn)中增加了一個(gè)方法 done 。
done 相當(dāng)于提供了一個(gè)不會(huì)出錯(cuò)的 catch 方法,并且不再返回一個(gè) promise ,一般用來結(jié)束一個(gè) promise 鏈。
done() { this.catch(reason => { console.log('done', reason); throw reason; }); }
finally() 方法
finally 方法用于無論是 resolve 還是 reject , finall y的參數(shù)函數(shù)都會(huì)被執(zhí)行。
finally(fn) { return this.then(value => { fn(); return value; }, reason => { fn(); throw reason; }); };
Promise.all() 方法
Promise.all 方法接收一個(gè) promise 數(shù)組,返回一個(gè)新 promise2 ,并發(fā)執(zhí)行數(shù)組中的全部 promise ,所有 promise 狀態(tài)都為 resolved 時(shí), promise2 狀態(tài)為 resolved 并返回全部 promise 結(jié)果,結(jié)果順序和 promise 數(shù)組順序一致。如果有一個(gè) promise 為 rejected 狀態(tài),則整個(gè) promise2 進(jìn)入 rejected 狀態(tài)。
static all(promiseList) { return new Promise((resolve, reject) => { const result = []; let i = 0; for (const p of promiseList) { p.then(value => { result[i] = value; if (result.length === promiseList.length) { resolve(result); } }, reject); i++; } }); }
Promise.race() 方法
Promise.race 方法接收一個(gè) promise 數(shù)組, 返回一個(gè)新 promise2 ,順序執(zhí)行數(shù)組中的 promise ,有一個(gè) promise 狀態(tài)確定, promise2 狀態(tài)即確定,并且同這個(gè) promise 的狀態(tài)一致。
static race(promiseList) { return new Promise((resolve, reject) => { for (const p of promiseList) { p.then((value) => { resolve(value); }, reject); } }); }
Promise.resolve() 和 Promise.reject()
Promise.resolve 用來生成一個(gè) rejected 完成態(tài)的 promise , Promise.reject 用來生成一個(gè) rejected 失敗態(tài)的 promise 。
static resolve(value) { let promise; promise = new Promise((resolve, reject) => { this.resolvePromise(promise, value, resolve, reject); }); return promise; } static reject(reason) { return new Promise((resolve, reject) => { reject(reason); }); }
附Promise 解決過程
Promise 解決過程是一個(gè)抽象的操作,其需輸入一個(gè) promise 和一個(gè)值,我們表示為 [[Resolve]](promise, x),如果 x 有 then 方法且看上去像一個(gè) Promise ,解決程序即嘗試使 promise 接受 x 的狀態(tài);否則其用 x 的值來執(zhí)行 promise 。
這種 thenable 的特性使得 Promise 的實(shí)現(xiàn)更具有通用性:只要其暴露出一個(gè)遵循 Promise/A+ 協(xié)議的 then 方法即可;這同時(shí)也使遵循 Promise/A+ 規(guī)范的實(shí)現(xiàn)可以與那些不太規(guī)范但可用的實(shí)現(xiàn)能良好共存。
運(yùn)行 [[Resolve]](promise, x) 需遵循以下步驟:
- x 與 promise 相等
如果 promise 和 x 指向同一對(duì)象,以 TypeError 為據(jù)因拒絕執(zhí)行 promise
- x 為 Promise
如果 x 為 Promise ,則使 promise 接受 x 的狀態(tài):
- 如果 x 處于等待態(tài), promise 需保持為等待態(tài)直至 x 被執(zhí)行或拒絕
- 如果 x 處于執(zhí)行態(tài),用相同的值執(zhí)行 promise
- 如果 x 處于拒絕態(tài),用相同的據(jù)因拒絕 promise
- x 為對(duì)象或函數(shù)
如果 x 為對(duì)象或者函數(shù):
- 把 x.then 賦值給 then
- 如果取 x.then 的值時(shí)拋出錯(cuò)誤 e ,則以 e 為據(jù)因拒絕 promise
- 如果 then 是函數(shù),將 x 作為函數(shù)的作用域 this 調(diào)用之。傳遞兩個(gè)回調(diào)函數(shù)作為參數(shù),第一個(gè)參數(shù)叫做 resolvePromise ,第二個(gè)參數(shù)叫做 rejectPromise:
- 如果 resolvePromise 以值 y 為參數(shù)被調(diào)用,則運(yùn)行 [[Resolve]](promise, y)
- 如果 rejectPromise 以據(jù)因 r 為參數(shù)被調(diào)用,則以據(jù)因 r 拒絕 promise
- 如果 resolvePromise 和 rejectPromise 均被調(diào)用,或者被同一參數(shù)調(diào)用了多次,則優(yōu)先采用首次調(diào)用并忽略剩下的調(diào)用
- 如果調(diào)用 then 方法拋出了異常 e:
- 如果 resolvePromise 或 rejectPromise 已經(jīng)被調(diào)用,則忽略之
- 否則以 e 為據(jù)因拒絕 promise
- 如果 then 不是函數(shù),以 x 為參數(shù)執(zhí)行 promise
- 如果 x 不為對(duì)象或者函數(shù),以 x 為參數(shù)執(zhí)行 promise
如果一個(gè) promise 被一個(gè)循環(huán)的 thenable 鏈中的對(duì)象解決,而 [[Resolve]](promise, thenable) 的遞歸性質(zhì)又使得其被再次調(diào)用,根據(jù)上述的算法將會(huì)陷入無限遞歸之中。算法雖不強(qiáng)制要求,但也鼓勵(lì)施者檢測(cè)這樣的遞歸是否存在,若檢測(cè)到存在則以一個(gè)可識(shí)別的 TypeError 為據(jù)因來拒絕 promise。
總結(jié)
常用的方法基本就這些, Promise 還有很多擴(kuò)展方法,這里就不一一展示,基本上都是對(duì) then 方法的進(jìn)一步封裝,只要你的 then 方法沒有問題,其他方法就都可以依賴 then 方法實(shí)現(xiàn)。
到此這篇關(guān)于Promise基本方法簡(jiǎn)單實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Promise基本方法實(shí)現(xiàn)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
動(dòng)態(tài)加載圖片路徑 保持JavaScript控件的相對(duì)獨(dú)立性
根據(jù)新界面的要求,需要一部分圖片來增強(qiáng)日期控件的美觀性。考慮到既要實(shí)現(xiàn)加載圖表的目標(biāo),又要保持控件的獨(dú)立性以便將來的移植。2010-09-09

js實(shí)現(xiàn)圖片旋轉(zhuǎn)的三種方法

CascadeView級(jí)聯(lián)組件實(shí)現(xiàn)思路詳解(分離思想和單鏈表)

JavaScript實(shí)現(xiàn)動(dòng)態(tài)生成表格案例詳解