摘要:而納入規(guī)范的也是建立在基礎上的。繼續(xù)閱讀的相關解釋語法其中函數(shù)擁有兩個參數(shù)和??梢钥吹?,在語法上看,還是有點像回調(diào)函數(shù)那種形式的,囧。完成操作已經(jīng)成功執(zhí)行完畢。消費,即對的所代表的值進行一系列的處理。
文 | Leigh,UPYUN 已獲得授權(quán)
原文鏈接:http://t.cn/R403hc4
在 JavaScript 這么多年發(fā)展中,尤其在前端領域框架層出不窮,解決方案也琳瑯滿目,Promise 這個思想也逐漸從一個框架層面的實現(xiàn)變成了 ES 的規(guī)范,并且越來越多的新 API 都在以 Promise 為基礎制定。是時候來看看這個怪物了!
什么是 Promise在 JavaScript 尤其是前端開發(fā)領域,Promise 已經(jīng)存在不少時日了,有一些曾經(jīng)廣受好評的第三方庫,例如 Q,when,Bluebird,RSVP,基本都曾名噪一時,盡管實現(xiàn)方式/API 不一樣,但它們大多都遵循著 Promises/A+ 這個‘事實規(guī)范’。而納入 ES 規(guī)范的 Promise API 也是建立在 Promises/A+ 基礎上的。
要注意的是,jQuery 雖然有一個類似 Promise 的 API,但是它的 Promise 實際上是被稱作為 Deferred 對象的一個東西,它跟 Promises/A+ 的規(guī)范是不太兼容。
Promise 主要用來解決 JS 開發(fā)中的異步問題,而對異步的處理,社區(qū)中也有著不少的解決方案,最多的就是回調(diào)這種形式,比如,在 Node.js 中:
這種書寫上的約定,很容易解決對異步操作的處理,但缺陷是,這樣的寫法,我們沒發(fā)直接在異步函數(shù)中進行 return 和 throw 操作,只能局限于回調(diào)的形式中,并且很容易引起回調(diào)金字塔的情況。Promise 則對異步處理和處理方法都做了規(guī)范和抽象,還給了開發(fā)者在異步代碼中使用 return 和 throw 的能力。而這也是 Promise 存在的真正意義。繼續(xù)閱讀 domenic 的相關解釋
語法其中 executor 函數(shù)擁有兩個參數(shù) resolve 和 reject。resolve 用于肯定 Promise,reject 用于否定它,我們可以在相關的操作結(jié)束后來執(zhí)行這兩個函數(shù)。
可以看到,在語法上看,Promise 還是有點像回調(diào)函數(shù)那種形式的,囧。不過,和回調(diào)函數(shù)相比,它的主要不同點在于:
1、每一個 Promise 都保證能讓我們收到一個值,Promise 便是這個值的代理,而我們無需關心它被創(chuàng)建的時間點,我們更可以在任意時刻注冊我們的結(jié)果處理函數(shù),即使這個 Promise 已經(jīng)完成(resolved)了(這時候,所注冊的處理函數(shù)會被立即執(zhí)行)。
2、每一個 Promise 都只會被成功或失敗一次,并且這個狀態(tài)不會被改變。
一個 Promise,會擁有以下幾個狀態(tài)之一:
1、pending(等待):操作正在執(zhí)行中。
2、fulfilled(完成):操作已經(jīng)成功執(zhí)行完畢。
3、reject(失敗):操作執(zhí)行失敗。
某些文章中可能會說到 settled 這個詞,settled 代表 Promise 不是 pending 的狀態(tài),即:要么是 fulfilled,要么是 reject。但他本身并不是一個狀態(tài),只是為了說的時候方便。詳見 domenic: States and Fates
Promise 的狀態(tài)變化圖如下:
使用 Promise創(chuàng)建
創(chuàng)建一個 Promise,直接的方法是直接 new Promise 創(chuàng)建一個,即上文中語法中所述一樣。其接受一個 executor 函數(shù)作為參數(shù)傳遞,Promise 在 executor 函數(shù)中提供了 resolve 和 reject 兩個函數(shù)供開發(fā)者根據(jù)實際結(jié)果來調(diào)用。
在 Promise 對象上,還有 Promise.all(iterable), Promise.race(iterable), Promise.reject(reason), Promise.resolve(value) 四個方法,這些方法也會返回 Promise 對象,因此,我們也可以通過這些方法來直接創(chuàng)建一個方法,例如 var p = Promise.resolve("I am a Promise!");
消費
Promise 一旦創(chuàng)建,我們就可以把它當做一個值來傳遞,因為 Promise 就是對一個未來會得到的值的代表。因此,你可以將它從函數(shù)中返回(return),也可以當做參數(shù)來傳遞到需要的地方,就像傳遞一個普通的值一樣。
消費 Promise,即對 Promise 的所代表的值進行一系列的處理。這里,我們可以使用 .then() 方法。
.then() 方法可以接受兩個函數(shù)作為參數(shù),第一個參數(shù)的函數(shù)會在 Promise 完成(fulfilled)的時候被調(diào)用,而第二個參數(shù)的函數(shù)則在 Promise 失敗 (rejected)的時候調(diào)用。這兩個參數(shù)都是可以被省略的:
每個 Promise 實例還有一個 .catch() 方法,主要用于對錯誤的處理,對于 .catch() 的方法理解,其實很簡單,它就相當于 .then() 省略第一個參數(shù):
上述兩種形式對錯誤的處理是等效的,當 Promise 失敗的時候,兩段代碼的執(zhí)行結(jié)果一樣。不過,一般情況下,更加推薦使用 .catch() 方法來處理錯誤,因為 catch 本身名字更加直接易懂,并且,在鏈式調(diào)用 Promise 的時候,只需要在調(diào)用鏈最末端使用一個 .catch() 即可。
在 Promise 中,當直接 throw 一個異常的時候,將會使該 Promise 置為 rejected 狀態(tài),這里需要注意的是,在 Promise 鏈中拋出異常,僅僅會將拋出異常所在的 Promise 置為 rejected,而不會影響原始的 Promise,比如:
處理多個異步操作
Promise.all()
在很多時候,我們都希望多個異步操作能夠并行,但很多情況下,我們又希望能在這多個異步操作全部都完成后再對結(jié)果進行處理,這個時候,我們就會用到 Promise.all(),這個方法接受一個 Promise 數(shù)組作為參數(shù),且會在所有 Promise 完成后執(zhí)行一次回調(diào) .then(),在這里,所有數(shù)組中的 Promise 都是并行方式執(zhí)行的,如下:
注意:只要一旦有一個 promise 失敗,.catch() 中的邏輯就會被執(zhí)行。
Promise.all() 在一些大型 web app 中,將會很有用,因為大多良好的 API 設計都是以數(shù)據(jù)維度劃分,產(chǎn)品的某一個功能,可能會涉及到多個 API 的數(shù)據(jù)聯(lián)動,這時候,使用 Promise.all() 即可方便的解決。
Promise.race()Promise.race() 它同樣接受一個 Promise 數(shù)組作為參數(shù),顧名思義,"race" 即比賽,想象一下,在平時百米競賽時候,一旦有人率先沖過終點,那變產(chǎn)生了一個冠軍,Promise.race() 即是在數(shù)組中的任意一個 Promise 完成后,便會觸發(fā) .then() 的邏輯,當然,這里數(shù)組中的 Promise 也是并行的:
Promise.race() 的經(jīng)典使用場景是某個服務有多個互備的形式,而我們需要盡快的拿到結(jié)果。
Series
并行很容易,但是 Promise 并沒有一個直接使用的串行的方法,當然,結(jié)合一些函數(shù)式編程的方法,我們可以很簡單的自行實現(xiàn)一下:
總結(jié)Promise 最近變得越來越火,無論前端領域,例如:Fetch API,Battery API,以及還未完成的 ServiceWorker API 等,甚至在 Node.js 社區(qū)中,人氣很高的 co,以及 koa 新版本都將 thunk 的形式改為了 Promise,在實際生產(chǎn)中投入使用,阻力也不會太大。
連接ES 規(guī)范
MDN 文檔
Can I Use 兼容性參考
es6-promise polyfill
歡迎關注 UPYUN 微信公眾號( ID : upaiyun ),我們每周都會分享高質(zhì)量的原創(chuàng)技術(shù)文章。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/78491.html
摘要:詳情發(fā)布于月號發(fā)布了版本,除了性能改進修復外,首次添加了貢獻者的安裝腳本。詳情中的應用在中悄悄增加了對漸進式應用這一系列新技術(shù)的基本支持,這意味著現(xiàn)在可以在沒有批準的情況下在上安裝應用程序,不過會有一些限制。 01. ES2016, 2017, 2018 中的新特性 文章介紹了 18 個 ECMAScript 2016,2017 和 2018 中新增加的特性,這些特性已被加入到 TC3...
摘要:詳情發(fā)布于月號發(fā)布了版本,除了性能改進修復外,首次添加了貢獻者的安裝腳本。詳情中的應用在中悄悄增加了對漸進式應用這一系列新技術(shù)的基本支持,這意味著現(xiàn)在可以在沒有批準的情況下在上安裝應用程序,不過會有一些限制。 01. ES2016, 2017, 2018 中的新特性 文章介紹了 18 個 ECMAScript 2016,2017 和 2018 中新增加的特性,這些特性已被加入到 TC3...
摘要:詳情發(fā)布于月號發(fā)布了版本,除了性能改進修復外,首次添加了貢獻者的安裝腳本。詳情中的應用在中悄悄增加了對漸進式應用這一系列新技術(shù)的基本支持,這意味著現(xiàn)在可以在沒有批準的情況下在上安裝應用程序,不過會有一些限制。 01. ES2016, 2017, 2018 中的新特性 文章介紹了 18 個 ECMAScript 2016,2017 和 2018 中新增加的特性,這些特性已被加入到 TC3...
摘要:本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個人總結(jié)給出了比較詳盡的答案。網(wǎng)易阿里騰訊校招社招必備知識點。此外還有網(wǎng)絡線程,定時器任務線程,文件系統(tǒng)處理線程等等。線程核心是引擎。主線程和工作線程之間的通知機制叫做事件循環(huán)。 showImg(https://segmentfault.com/img/bVbu4aB?w=300&h=208); 本文總結(jié)了前端老司機經(jīng)常問題的一些問題并結(jié)合個...
閱讀 1878·2019-08-29 16:44
閱讀 2182·2019-08-29 16:30
閱讀 791·2019-08-29 15:12
閱讀 3534·2019-08-26 10:48
閱讀 2668·2019-08-23 18:33
閱讀 3788·2019-08-23 17:01
閱讀 1948·2019-08-23 15:54
閱讀 1311·2019-08-23 15:05