Promise 的使用

使用Promise

基本用法

A Promise is an object representing the eventual completion or failure of an asynchronous operation. Promise是表示異步操作最終完成或失敗的對象。

Promise 本質(zhì)上是一個綁定了回調(diào)函數(shù)的對象。不同于我們平時看到的將回調(diào)作為參數(shù)傳遞給一個函數(shù)的形式。

首先來看下,我們熟悉的將回調(diào)作為函數(shù)傳遞給函數(shù)的例子:

    function successCallback(result) {
      console.log("Audio file ready at URL: " + result);
    }
    
    function failureCallback(error) {
      console.log("Error generating audio file: " + error);
    }
    
    createAudioFileAsync(audioSettings, successCallback, failureCallback);

上面這個函數(shù)作用是異步的創(chuàng)建一個音頻文件碘橘,第一個參數(shù)是配置對象,第二和第三個分別是創(chuàng)建音頻文件成功和失敗后的回調(diào)函數(shù)脖旱。

那如果將上面的例子用Promise來處理久窟,會是怎樣的形式呢东抹?

  1. Promise用then來表示處理結(jié)果

     createAudioFileAsync(audioSettings).then(successfulCallback, failureCallback)
    
  2. 也可以寫成另外一種簡化形式

     createAudioFileAsync(audioSettings).then(successfulCallback).catch(failureCallback)
    

我個人喜歡第二種形式蚂子,可讀性更強一些

Chain 鏈式調(diào)用

這個是Promise一個特別有意思的用法,對于處理多個串行的異步調(diào)用非常好用缭黔。

考慮這樣的場景食茎,我們要處理多個異步調(diào)用,每一個異步的調(diào)用都要利用前一個的結(jié)果试浙。那么就可以使用promise的chain董瞻。

例如,我們要獲取某些資源田巴,并且對資源處理之后钠糊,發(fā)送PUT請求更新資源的結(jié)果。而第一步是驗證用戶的合法性壹哺,是否具有這樣操作的權(quán)限抄伍。那么用Promise就可以寫成如下形式:

LoginPromise(userProfile)
    .then(resp => {
        if (resp.status == OK) return resp.authToken;
    })
    .then(token => {
       return axios.get(url, {authToken: token}); 
    })
    .then(resp => {
      let resource = prepareResource();
      return axios.post(url, {resource: resource}, header);
    })
    .catch(err => {
      console.log(err);
    })

上述的代碼就會比之前嵌套的回調(diào)要優(yōu)雅而且表意很多。

當然管宵,catch之后依然還可以跟then截珍,表示出錯之后的繼續(xù)處理。

改造舊的異步調(diào)用

我們可能會碰到許多已經(jīng)存在的異步調(diào)用箩朴,如何使用Promise來改造他們呢岗喉,看一下下面這個例子:

setTimeout(() => saySomething("10 seconds passed"), 10000);

setTimeout 設(shè)置一個定時器,在10000ms之后發(fā)出消息炸庞。

const wait = ms => new Promise(resolve => setTimeout(resolve, ms));

wait(10000).then(() => saySomething("10 seconds")).catch(failureCallback);

可以看到wait只是作為一個Promise對象存在钱床,至于回調(diào)要做什么,在then中可以來設(shè)置埠居。

組合

Promise.resolve() 和 Promise.reject() 可以手動創(chuàng)建一個已經(jīng)resolve或者reject的Promise對象查牌。在某些場景下是一個非常有用的特性事期。

Promise.all() 和 Promise.race() 用來處理并行的Promise。

例如下面的代碼纸颜,就使用了Promise和reduce:

[func1, func2].reduce((p, f) => p.then(f), Promise.resolve());

首先創(chuàng)建Promise.resolve()兽泣,然后依次處理func1和func2. 上述代碼等價于:

Promise.resolve().then(func1).then(func2);

以此類推,就可以將上述代碼擴展到多個函數(shù)的處理:

const applyAsync = (acc,val) => acc.then(val);
const composeAsync = (...funcs) => x => funcs.reduce(applyAsync, Promise.resolve(x));

composeAsync是一個接收可變參數(shù)作為一組回調(diào)函數(shù)的函數(shù)胁孙。使用方式如下:

const transformData = composeAsync(func1, asyncFunc1, asyncFunc2, func2);

composeAsync 的返回值是一個函數(shù)唠倦,此函數(shù)輸入?yún)?shù)為x,執(zhí)行Promise.resolve(x).then(func1).then(func2).then(func3)...

transformData(data)

這個函數(shù)實現(xiàn)的功能是對data浊洞,由一組函數(shù)(func1, asyncFunc1, asyncFunc2, func2)來處理牵敷。

Nesting

這里需要注意的是Promise的Nesting,嵌套法希。如果你想實現(xiàn)的是Promise的串行調(diào)用,那么就一定使用Promise的Chain來操作靶瘸。

如果出現(xiàn)Promise的嵌套苫亦,就會出現(xiàn)一些隱藏的問題,看如下的例子:

promise1()
    .then(res => {
      promise2(res)
        .then(newRes => {
        })
        .catch(err) {
          console.log(err)
        }
    })
    .then(result => {
      promise3()
        .then( () => {})
        .catch(() => {})
    })
    .catch(err => {})

上述代碼中怨咪,也許你想在promise2出現(xiàn)失敗的情況下屋剑,后續(xù)的異步操作promise3不用再執(zhí)行,但實際上做不到诗眨,內(nèi)層的catch并不會傳遞到外層唉匾,所以then.promise3就會繼續(xù)執(zhí)行下去。

容易出的錯

// Bad example! Spot 3 mistakes!

doSomething().then(function(result) {
  doSomethingElse(result) // Forgot to return promise from inner chain + unnecessary nesting
  .then(newResult => doThirdThing(newResult));
}).then(() => doFourthThing());
// Forgot to terminate chain with a catch!

上面的代碼有三處錯誤:

  • 內(nèi)層并沒有return新的promise匠楚,這樣就會到這外層不會等到內(nèi)層結(jié)束巍膘,而直接運行doFourthThing()。
  • nesting 在前面已經(jīng)分析過了
  • 沒有catch芋簿,在眾多瀏覽器中沒有catch會導(dǎo)致promise出錯

一個比較合理的promise例子如下:

doSomething()
.then(function(result) {
  return doSomethingElse(result);
})
.then(newResult => doThirdThing(newResult))
.then(() => doFourthThing());
.catch(error => console.log(error));
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末峡懈,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子与斤,更是在濱河造成了極大的恐慌肪康,老刑警劉巖,帶你破解...
    沈念sama閱讀 222,000評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件撩穿,死亡現(xiàn)場離奇詭異磷支,居然都是意外死亡,警方通過查閱死者的電腦和手機食寡,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,745評論 3 399
  • 文/潘曉璐 我一進店門雾狈,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人冻河,你說我怎么就攤上這事箍邮≤运В” “怎么了?”我有些...
    開封第一講書人閱讀 168,561評論 0 360
  • 文/不壞的土叔 我叫張陵锭弊,是天一觀的道長堪澎。 經(jīng)常有香客問我,道長味滞,這世上最難降的妖魔是什么樱蛤? 我笑而不...
    開封第一講書人閱讀 59,782評論 1 298
  • 正文 為了忘掉前任,我火速辦了婚禮剑鞍,結(jié)果婚禮上昨凡,老公的妹妹穿的比我還像新娘。我一直安慰自己蚁署,他們只是感情好便脊,可當我...
    茶點故事閱讀 68,798評論 6 397
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著光戈,像睡著了一般哪痰。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上久妆,一...
    開封第一講書人閱讀 52,394評論 1 310
  • 那天晌杰,我揣著相機與錄音,去河邊找鬼筷弦。 笑死肋演,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的烂琴。 我是一名探鬼主播爹殊,決...
    沈念sama閱讀 40,952評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼监右!你這毒婦竟也來了边灭?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,852評論 0 276
  • 序言:老撾萬榮一對情侶失蹤健盒,失蹤者是張志新(化名)和其女友劉穎绒瘦,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體扣癣,經(jīng)...
    沈念sama閱讀 46,409評論 1 318
  • 正文 獨居荒郊野嶺守林人離奇死亡惰帽,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,483評論 3 341
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了父虑。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片该酗。...
    茶點故事閱讀 40,615評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出呜魄,到底是詐尸還是另有隱情悔叽,我是刑警寧澤,帶...
    沈念sama閱讀 36,303評論 5 350
  • 正文 年R本政府宣布爵嗅,位于F島的核電站娇澎,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏睹晒。R本人自食惡果不足惜趟庄,卻給世界環(huán)境...
    茶點故事閱讀 41,979評論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望伪很。 院中可真熱鬧戚啥,春花似錦、人聲如沸锉试。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,470評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽键痛。三九已至炫彩,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間絮短,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,571評論 1 272
  • 我被黑心中介騙來泰國打工昨忆, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留丁频,地道東北人。 一個月前我還...
    沈念sama閱讀 49,041評論 3 377
  • 正文 我出身青樓邑贴,卻偏偏與公主長得像席里,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子拢驾,可洞房花燭夜當晚...
    茶點故事閱讀 45,630評論 2 359

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

  • title: promise總結(jié) 總結(jié)在前 前言 下文類似 Promise#then奖磁、Promise#resolv...
    JyLie閱讀 12,259評論 1 21
  • Promise 對象 Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,710評論 1 56
  • Prepending(進行時)繁疤,Resolve(成功了)咖为,Reject(失敗了),then......等 1.Pr...
    _菩提本無樹_閱讀 49,080評論 0 21
  • 本文適用的讀者 本文寫給有一定Promise使用經(jīng)驗的人稠腊,如果你還沒有使用過Promise躁染,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,313評論 6 19
  • … 剛才在浦園跑步 夜色濃重 迎面過來的一個小男孩 指著我大喊 媽媽架忌!你快看吞彤,這個男人有一身肌肉 … 小小年紀 怎...
    AI大叔閱讀 216評論 1 0