JS異步工具之--Promise

作者:杜珂珂 (滬江前端開發(fā)工程師)

本文為原創(chuàng)文章,有不當(dāng)之處歡迎指出。轉(zhuǎn)載請標(biāo)明出處掰派。

一個(gè)新事物的產(chǎn)生必然是有其歷史原因的。為了更好的以同步的方式寫異步的代碼左痢,人們在JS上操碎了心靡羡。從Deferred到Promise到Generator再到Async和Await,各種工具的涌現(xiàn)就像是人類文明的進(jìn)化史俊性,從無到有略步,從簡陋到完善。

在這其中磅废,Promise是較為重要的一個(gè)工具纳像,也是后面不同工具進(jìn)化完善的基石,今天我們就來了解一下:我們?yōu)槭裁葱枰狿romise以及Promise為我們解決了什么問題拯勉。

我們需要什么竟趾?

1. 回調(diào)地獄

我們應(yīng)該都遇到過這樣的代碼:

callback嵌套函數(shù)層數(shù)少了還好,如果更多的話宫峦,大量的縮進(jìn)會(huì)你的代碼慢慢地向屏幕右側(cè)移動(dòng)岔帽。如果你寫了幾十層回調(diào),那么你的代碼在一個(gè)屏幕的寬度上可能放不下了导绷。這會(huì)讓我們的代碼變得難以維護(hù)犀勒,像一坨*。誠然我們可以通過其它的方式,把代碼抽出來平級(jí)對待贾费,例如:

這么做雖然好看了钦购,但: 1. 切斷了我們代碼結(jié)構(gòu)上的層級(jí)串聯(lián),而是采用了非結(jié)構(gòu)的指向串聯(lián) 褂萧,跳來跳去的函數(shù)引用押桃,很可能就把我們繞暈了 2. 要耗費(fèi)更多的時(shí)間來整理代碼

我們想要的是:既能串起來寫,又能少花時(shí)間导犹。而Promise恰恰解決了這么一個(gè)痛點(diǎn)唱凯。

var promise = new Promise(...);

promise.then(...)

.then(...)

.then(...)

.then(...)

.catch(...)

對!我們其實(shí)要的就是這樣一種“語法糖”谎痢。

2. 不讓回調(diào)里的return和throw變成擺設(shè)

想想你在$.ajax()的success回調(diào)里寫個(gè)return xxx磕昼,沒啥用,return給誰节猿?這種感覺就像打了一記空拳票从。另外,你如果在異步回調(diào)里throw一個(gè)錯(cuò)誤滨嘱,外面想接一下纫骑,比如你想這樣:

恭喜你!接不到九孩,error被扔到全局環(huán)境里去了,BOOM发框!然后主線程就掛了躺彬。

Promise解決方案是什么?

首先在字面意思上看Promise梅惯,翻譯成“承諾”的話有些抽象宪拥。那么具象一點(diǎn),我們可以把Promise看成某種“合約”的管理者和執(zhí)行者铣减。

對她君,我們可以先把“他”想象成一個(gè)人,給他起一個(gè)簡短的名字葫哗,叫做:“P先生”缔刹。下面,就來看一下劣针,“P先生”是如何幫助我們解決問題的(由于解決方案是“P先生”提供的校镐,所以我們需要按照“他”的套路來)。

1. ?定下合約

首先捺典,我們需要按照某個(gè)模板的樣子寫下一個(gè)“合約”鸟廓,“合約”里告訴“P先生”的是將來可能發(fā)生的事情,“P先生”針對我們和“他”約定的事項(xiàng),做不同的處理和反饋引谜。Promise只對未來發(fā)生的事情做出兩種基本情況的應(yīng)對:“成功” 和 “失敗”牍陌。

上述代碼中,首先我們召喚(new)了一個(gè)“P先生”员咽,然后在回調(diào)函數(shù)里告訴了“他”具體的合約內(nèi)容毒涧,合約規(guī)定:在setTimeout異步操作中,如果得到的秒數(shù)大于30s骏融,則合約生效并且完成链嘀;否則的話,合約無效并且完成档玻』巢矗“P先生”點(diǎn)點(diǎn)頭說:“好的,沒問題”误趴。

注意:一旦做完resolve或者reject操作霹琼,合約的狀態(tài)就算定死了,沒辦法再改動(dòng)了凉当。

2. 合約完成后的操作

上一步做完枣申,“P先生”只會(huì)告訴我們合約完成的結(jié)果:成功 或 失敗。那么成功后該怎么做看杭?失敗后該怎么做忠藤?我們還沒有告訴“P先生”,下面揮一揮小手(引用promise變量)楼雹,把“P先生”招過來模孩,繼續(xù)囑咐:

then給出了應(yīng)對成功或失敗具體需要的方案,里面需要傳兩個(gè)處理函數(shù)

如果then中只傳遞了onRejected函數(shù)的話贮缅,那么相當(dāng)于catch榨咐。

看到這里,我們發(fā)現(xiàn)Promise一定程度上幫我們解決了錯(cuò)誤捕獲的問題谴供。上述例子块茁,我們在then鏈中產(chǎn)生的錯(cuò)誤,最后都能被catch捕捉到(前提是你在最后面寫了catch)桂肌。

then里面的函數(shù)該寫點(diǎn)什么数焊?

每一個(gè) promise 都會(huì)提供給你一個(gè) then()函數(shù)。當(dāng)我們的代碼跑在 then()函數(shù)內(nèi)部時(shí)轴或,是這樣子的:

在這個(gè)函數(shù)內(nèi)部我們可以做什么呢昌跌?

也就是說我可以這么寫:

在上面的例子中看到,我們能在then中愉快的使用return和throw照雁,并順利將值傳遞給下一層then或catch來處理蚕愤。到這里Promise其實(shí)已經(jīng)解決了之前我們說過的問題:“在異步回調(diào)里不能有效的使用return和throw”

總結(jié)

看到這里答恶,想必各位看官應(yīng)該已經(jīng)清楚的認(rèn)識(shí)到Promise是個(gè)什么東西,并幫助我們解決了什么問題吧萍诱?當(dāng)然悬嗓,Promise API還提供了很多的方法,比如race,?all裕坊,reject,?resolve包竹。本文的主要目的還是為了解釋Promise產(chǎn)生的原因和“他”解決了什么問題,至于API上的其它方法籍凝,相信在理解Promise的基礎(chǔ)上周瞎,會(huì)很容易就掌握的。

在異步“轉(zhuǎn)”同步這條道路上饵蒂,Promise只是一個(gè)出彩的點(diǎn)声诸,“他”還尚有一些缺陷和不足,并不是我們最終的解決方案退盯。下一次彼乌,我們將一起學(xué)習(xí)新的工具:Generator!

參考資料:

【翻譯】We have a problem with promises

JavaScript Promise迷你書(中文版)

ES6 JavaScript Promise的感性認(rèn)知

Promise?- JavaScript |?MDN

如果喜歡本文渊迁,可以訂閱滬江技術(shù)學(xué)院公眾號(hào)慰照。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市琉朽,隨后出現(xiàn)的幾起案子毒租,更是在濱河造成了極大的恐慌,老刑警劉巖箱叁,帶你破解...
    沈念sama閱讀 206,968評論 6 482
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蝌衔,死亡現(xiàn)場離奇詭異,居然都是意外死亡蝌蹂,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,601評論 2 382
  • 文/潘曉璐 我一進(jìn)店門曹锨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來孤个,“玉大人,你說我怎么就攤上這事沛简∑肜穑” “怎么了?”我有些...
    開封第一講書人閱讀 153,220評論 0 344
  • 文/不壞的土叔 我叫張陵椒楣,是天一觀的道長给郊。 經(jīng)常有香客問我,道長捧灰,這世上最難降的妖魔是什么淆九? 我笑而不...
    開封第一講書人閱讀 55,416評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上炭庙,老公的妹妹穿的比我還像新娘饲窿。我一直安慰自己,他們只是感情好焕蹄,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,425評論 5 374
  • 文/花漫 我一把揭開白布逾雄。 她就那樣靜靜地躺著,像睡著了一般腻脏。 火紅的嫁衣襯著肌膚如雪鸦泳。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,144評論 1 285
  • 那天永品,我揣著相機(jī)與錄音做鹰,去河邊找鬼。 笑死腐碱,一個(gè)胖子當(dāng)著我的面吹牛誊垢,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播症见,決...
    沈念sama閱讀 38,432評論 3 401
  • 文/蒼蘭香墨 我猛地睜開眼喂走,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了谋作?” 一聲冷哼從身側(cè)響起芋肠,我...
    開封第一講書人閱讀 37,088評論 0 261
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎遵蚜,沒想到半個(gè)月后帖池,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,586評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡吭净,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,028評論 2 325
  • 正文 我和宋清朗相戀三年睡汹,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片寂殉。...
    茶點(diǎn)故事閱讀 38,137評論 1 334
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡囚巴,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出友扰,到底是詐尸還是另有隱情彤叉,我是刑警寧澤,帶...
    沈念sama閱讀 33,783評論 4 324
  • 正文 年R本政府宣布村怪,位于F島的核電站秽浇,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏甚负。R本人自食惡果不足惜柬焕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,343評論 3 307
  • 文/蒙蒙 一审残、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧击喂,春花似錦维苔、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,333評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至凌彬,卻和暖如春沸柔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背铲敛。 一陣腳步聲響...
    開封第一講書人閱讀 31,559評論 1 262
  • 我被黑心中介騙來泰國打工褐澎, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人伐蒋。 一個(gè)月前我還...
    沈念sama閱讀 45,595評論 2 355
  • 正文 我出身青樓工三,卻偏偏與公主長得像,于是被迫代替她去往敵國和親先鱼。 傳聞我的和親對象是個(gè)殘疾皇子俭正,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,901評論 2 345

推薦閱讀更多精彩內(nèi)容