淺談Promise對(duì)象在ReactNative中的使用

寫(xiě)在前面

假設(shè)現(xiàn)在一個(gè)日常開(kāi)發(fā)會(huì)遇到這樣一個(gè)需求:多個(gè)接口異步請(qǐng)求嘴高,第二個(gè)接口依賴于第一個(gè)接口執(zhí)行完畢之后才能利用數(shù)據(jù)進(jìn)行一系列操作。一般會(huì)這樣寫(xiě):

            A.fetchData({
                url: 'http://......',
                success: function (data) {
                    A.fetchData({
                        // 要在第一個(gè)請(qǐng)求成功后才可以執(zhí)行下一步
                        url: 'http://......',
                        success: function (data) {
                             // ......
                        }
                    });
                }
            });

這樣寫(xiě)沒(méi)問(wèn)題舔痪,但是有兩個(gè)缺點(diǎn):
1、當(dāng)有多個(gè)操作的時(shí)候,會(huì)導(dǎo)致多個(gè)回調(diào)函數(shù)嵌套付秕,不夠美觀
2、如果有幾個(gè)操作沒(méi)有前后順序之分時(shí)侍郭,例如上面的后一個(gè)請(qǐng)求不依賴與前一個(gè)請(qǐng)求的返回結(jié)果的時(shí)候询吴,同樣也需要等待上一個(gè)操作完成再實(shí)行下一個(gè)操作。

從ES6開(kāi)始亮元,Promise對(duì)象可以解決上述問(wèn)題猛计。

什么是Promise對(duì)象

一個(gè)Promise對(duì)象可以理解為一次將要執(zhí)行的操作,使用了Promise對(duì)象之后可以用一種鏈?zhǔn)秸{(diào)用的方式來(lái)組織代碼爆捞,讓代碼更加直觀奉瘤。

resolve和reject

先看代碼:

  function helloWorld (ready) {
    return new Promise(function (resolve, reject) {
        if (ready) {
            resolve("Hello World!");
        } else {
            reject("Good bye!");
        }
    });
  }

    helloWorld(true).then(function (message) {
        alert(message);
    }, function (error) {
        alert(error);
    });

上面的代碼實(shí)現(xiàn)的功能非常簡(jiǎn)單,helloWord 函數(shù)接受一個(gè)參數(shù)煮甥,如果為 true 就打印 "Hello World!"盗温,如果為 false 就打印錯(cuò)誤的信息。helloWord 函數(shù)返回的是一個(gè) Promise 對(duì)象成肘。

在 Promise 對(duì)象當(dāng)中有兩個(gè)重要方法————resolve 和 reject卖局。

resolve 方法可以使 Promise 對(duì)象的狀態(tài)改變成成功,同時(shí)傳遞一個(gè)參數(shù)用于后續(xù)成功后的操作双霍,在這個(gè)例子當(dāng)中就是 Hello World! 字符串砚偶。

reject 方法則是將 Promise 對(duì)象的狀態(tài)改變?yōu)槭。瑫r(shí)將錯(cuò)誤的信息傳遞到后續(xù)錯(cuò)誤處理的操作洒闸。

then

Promise 對(duì)象有三種狀態(tài):
1.Fulfilled 可以理解為成功的狀態(tài)
2.Rejected 可以理解為失敗的狀態(tài)
3.Pending 既不是 Fulfilld 也不是 Rejected 的狀態(tài)染坯,可以理解為 Promise 對(duì)象實(shí)例創(chuàng)建時(shí)候的初始狀態(tài)。

helloWorld 的例子中的 then方法就是根據(jù) Promise 對(duì)象的狀態(tài)來(lái)確定執(zhí)行的操作丘逸,resolve 時(shí)執(zhí)行第一個(gè)函數(shù)(onFulfilled)单鹿,reject 時(shí)執(zhí)行第二個(gè)函數(shù)(onRejected)。promise模式在任何時(shí)刻都處于以下三種狀態(tài)之一:未完成(unfulfilled)深纲、已完成(resolved)和拒絕(rejected)仲锄。以CommonJS Promise/A 標(biāo)準(zhǔn)為例,promise對(duì)象上的then方法負(fù)責(zé)添加針對(duì)已完成和拒絕狀態(tài)下的處理函數(shù)囤萤。then方法會(huì)返回另一個(gè)promise對(duì)象昼窗,以便于形成promise管道,這種返回promise對(duì)象的方式能夠支持開(kāi)發(fā)人員把異步操作串聯(lián)起來(lái)涛舍,如then(resolvedHandler, rejectedHandler); 澄惊。resolvedHandler 回調(diào)函數(shù)在promise對(duì)象進(jìn)入完成狀態(tài)時(shí)會(huì)觸發(fā),并傳遞結(jié)果;rejectedHandler函數(shù)會(huì)在拒絕狀態(tài)下調(diào)用掸驱。

示例代碼1:

function printHello (ready) {
  var promise = new Promise(function (resolve, reject) {
      if (ready) {
          resolve("Hello");
      } else {
          reject("Good bye");
      }
  });
  return promise;
}

function printWorld () {
    console.log('World');
}

function printExclamation () {
    console.log('!!!');
}

 printHello(true)
 .then(function(message)
 .then(printWorld)
 .then(printExclamation)
 .catch(function(error){
    console.log(error);
  });;

函數(shù)先執(zhí)行printHello肛搬,返回一個(gè)promise對(duì)象,通過(guò)then將異步操作串聯(lián)起來(lái)毕贼。
執(zhí)行結(jié)果應(yīng)該是 Hello
World
!!!

示例代碼2:

  function helloWorld (ready) {
    return new Promise(function (resolve, reject) {
        if (ready) {
            resolve("Hello World!");
        } else {
            reject("Good bye!");
        }
    });
  }

  var _this = this;
  printHello(true)
  .then(function (message) {
  var REQUEST_URL = 'https://raw.githubusercontent.com/facebook/react-native/master/docs/MoviesExample.json';
   return  fetch(REQUEST_URL)
      .then((response) => response.json())
      .then((responseData) => {
        var movie = responseData.movies[1];
        console.log('data   =   ', movie.title);
        return movie.title;
      })
  },function (error) {
      return(error);
  }).then(function (message) {
      return message  + ' World';
  }).then(function (message) {
      return message + '!!!';
  }).then(function (message) {
     console.log(message);
     console.log('finally');
  }).catch(function(error){
     console.log(error);
  });

上面的代碼中有兩個(gè)promise温赔,第一個(gè)promise執(zhí)行完畢后也就是printHello之后,會(huì)執(zhí)行下一個(gè)then,這個(gè)then返回了一個(gè)獲取數(shù)據(jù)的promise鬼癣,后面的then拿到的promise都是指向這個(gè)promise對(duì)象的陶贼。上述例子通過(guò)鏈?zhǔn)秸{(diào)用的方式,按順序打印出了相應(yīng)的內(nèi)容待秃。then 可以使用鏈?zhǔn)秸{(diào)用的寫(xiě)法原因在于拜秧,每一次執(zhí)行該方法時(shí)總是會(huì)返回一個(gè) Promise 對(duì)象。另外章郁,在 then onFulfilled 的函數(shù)當(dāng)中的返回值枉氮,可以作為后續(xù)操作的參數(shù)。

catch

catch 方法是 then(onFulfilled, onRejected) 方法當(dāng)中 onRejected 函數(shù)的一個(gè)簡(jiǎn)單的寫(xiě)法暖庄,也就是說(shuō)可以寫(xiě)成 then(fn).catch(fn)聊替,相當(dāng)于 then(fn).then(null, fn)。使用 catch 的寫(xiě)法比一般的寫(xiě)法更加清晰明確培廓。

新手使用容易犯的錯(cuò)誤

1.忘記添加catch()方法

這是一個(gè)很常見(jiàn)的錯(cuò)誤惹悄。很多程序員對(duì)他們代碼中的promise調(diào)用十分自信,覺(jué)得代碼永遠(yuǎn)不會(huì)拋出一個(gè) error 医舆,也可能他們只是簡(jiǎn)單的忘了加 catch() 方法俘侠。不幸的是象缀,不加 catch() 方法會(huì)讓回調(diào)函數(shù)中拋出的異常被吞噬蔬将,在你的控制臺(tái)是看不到相應(yīng)的錯(cuò)誤的,這對(duì)調(diào)試來(lái)說(shuō)是非常痛苦的央星。

為了避免這種糟糕的情況霞怀,我已經(jīng)養(yǎng)成了在自己的promise調(diào)用鏈最后添加如下代碼的習(xí)慣:

      somePromise().then(function () {
        return aPromise();
      }).then(function () {
        return anotherPromise();
      }).catch(function(error){
               console.log(error);
            });

即使你并不打算在代碼中處理異常,在代碼中添加 catch() 也是一個(gè)謹(jǐn)慎的編程風(fēng)格的體現(xiàn)莉给。在某種情況下你原先的假設(shè)出錯(cuò)的時(shí)候毙石,這會(huì)讓你的調(diào)試工作輕松一些。

2.return的混淆亂用

在then方法內(nèi)部颓遏,我們可以做三件事:
1.return 一個(gè)promise對(duì)象
2.return一個(gè)同步的值或者是 undefined
3.同步的 throw 一個(gè)錯(cuò)誤

理解這三種情況之后徐矩,你就會(huì)理解promise了。

1.返回另一個(gè)promise對(duì)象

在有關(guān)promise的相關(guān)文章中叁幢,這種寫(xiě)法很常見(jiàn)滤灯,就像上文提到的構(gòu)成promise鏈的一段代碼:

        getUserByName('nolan').then(function (user) {
            
          return fetch(REQUEST_URL)
                .then((response) => response.json())
                .then((responseData) => {
         
                 }      
                        
        }).then(function () {
        });

2.返回一個(gè)具體的值或者是 undefined

    getUserByName('nolan').then(fcuntion (user) {
        if (inMemoryCache[user.id]) {
            return inMemoryCache[user.id];  
            // returning a value!
        }
        return inMemoryCache[user.id];
         // returning a promise
    }).then(function (userAccount) {
        // I got a user account
    })

如果不調(diào)用return語(yǔ)句的話,javaScript里的函數(shù)會(huì)返回 undefined 。這也就意味著在你想返回一些值的時(shí)候鳞骤,不顯式調(diào)用return會(huì)產(chǎn)生一些副作用窒百。

出于上述原因,養(yǎng)成了一個(gè)個(gè)人習(xí)慣就是在then方法內(nèi)部永遠(yuǎn)顯式的調(diào)用return或者throw豫尽。我也推薦你這樣做篙梢。

3.拋出一個(gè)錯(cuò)誤

說(shuō)到throw,這又體現(xiàn)了promise的功能強(qiáng)大美旧。在用戶退出的情況下渤滞,我們的代碼中會(huì)采用拋出異常的方式進(jìn)行處理:

    getUserByName('nolan').then(function (user) {
      if (user.isLoggedOut()) {
        throw new Error('user logged out!'); 
        // throwing a error!
      }
      if (inMemoryCache[user.id]) {
        return inMemoryCache[user.id];      
         // returning a value!
      }
      return getUserAccountById(user.id);   
       // returning a promise!
    }).then(function (userAccount) {
      // I got a user account!
    }).catch(function (err) {
      // Boo, I got an error!
    });

如果用戶已經(jīng)登出的話, catch() 會(huì)收到一個(gè)錯(cuò)誤榴嗅,如果有promise對(duì)象的狀態(tài)變?yōu)閞ejected的話蔼水,它還會(huì)收到一個(gè)錯(cuò)誤。
在使用promise的時(shí)候拋出異常在開(kāi)發(fā)階段很有用录肯,它能幫助我們定位代碼中的錯(cuò)誤趴腋。比方說(shuō),在then函數(shù)內(nèi)部調(diào)用 JSON.parse() 论咏,如果JSON對(duì)象不合法的話优炬,可能會(huì)拋出異常,在回調(diào)函數(shù)中厅贪,這個(gè)異常會(huì)被吞噬蠢护,但是在使用promise之后,我們就可以捕獲到這個(gè)異常了养涮。

微博賬號(hào):梅嘉慶(點(diǎn)擊關(guān)注)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末葵硕,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子贯吓,更是在濱河造成了極大的恐慌懈凹,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評(píng)論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件悄谐,死亡現(xiàn)場(chǎng)離奇詭異介评,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)爬舰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門(mén)们陆,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人情屹,你說(shuō)我怎么就攤上這事坪仇。” “怎么了垃你?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,083評(píng)論 0 355
  • 文/不壞的土叔 我叫張陵椅文,是天一觀的道長(zhǎng)颈墅。 經(jīng)常有香客問(wèn)我,道長(zhǎng)雾袱,這世上最難降的妖魔是什么恤筛? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,763評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮芹橡,結(jié)果婚禮上毒坛,老公的妹妹穿的比我還像新娘。我一直安慰自己林说,他們只是感情好煎殷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,785評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著腿箩,像睡著了一般豪直。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上珠移,一...
    開(kāi)封第一講書(shū)人閱讀 51,624評(píng)論 1 305
  • 那天弓乙,我揣著相機(jī)與錄音,去河邊找鬼钧惧。 笑死暇韧,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的浓瞪。 我是一名探鬼主播懈玻,決...
    沈念sama閱讀 40,358評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼乾颁!你這毒婦竟也來(lái)了涂乌?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 39,261評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤英岭,失蹤者是張志新(化名)和其女友劉穎湾盒,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體巴席,經(jīng)...
    沈念sama閱讀 45,722評(píng)論 1 315
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡历涝,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,900評(píng)論 3 336
  • 正文 我和宋清朗相戀三年诅需,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了漾唉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,030評(píng)論 1 350
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡堰塌,死狀恐怖赵刑,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情场刑,我是刑警寧澤般此,帶...
    沈念sama閱讀 35,737評(píng)論 5 346
  • 正文 年R本政府宣布蚪战,位于F島的核電站,受9級(jí)特大地震影響铐懊,放射性物質(zhì)發(fā)生泄漏邀桑。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,360評(píng)論 3 330
  • 文/蒙蒙 一科乎、第九天 我趴在偏房一處隱蔽的房頂上張望壁畸。 院中可真熱鬧,春花似錦茅茂、人聲如沸捏萍。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,941評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)令杈。三九已至,卻和暖如春碴倾,著一層夾襖步出監(jiān)牢的瞬間逗噩,已是汗流浹背嚎莉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,057評(píng)論 1 270
  • 我被黑心中介騙來(lái)泰國(guó)打工募书, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人蓬坡。 一個(gè)月前我還...
    沈念sama閱讀 48,237評(píng)論 3 371
  • 正文 我出身青樓矫户,卻偏偏與公主長(zhǎng)得像片迅,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子皆辽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,976評(píng)論 2 355

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

  • 00驱闷、前言Promise 是異步編程的一種解決方案耻台,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)...
    夜幕小草閱讀 2,133評(píng)論 0 12
  • 本文適用的讀者 本文寫(xiě)給有一定Promise使用經(jīng)驗(yàn)的人空另,如果你還沒(méi)有使用過(guò)Promise盆耽,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,310評(píng)論 6 19
  • Promise的含義: ??Promise是異步編程的一種解決方案扼菠,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和...
    呼呼哥閱讀 2,170評(píng)論 0 16
  • Promiese 簡(jiǎn)單說(shuō)就是一個(gè)容器摄杂,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果,語(yǔ)法上說(shuō)循榆,Pr...
    雨飛飛雨閱讀 3,358評(píng)論 0 19
  • 微信oauth前后端分離實(shí)現(xiàn) 在前后端分離的基礎(chǔ)上析恢,實(shí)現(xiàn)微信的oauth機(jī)制 如何獲取微信用戶信息 頁(yè)面如果需要獲...
    nothingp閱讀 3,694評(píng)論 0 1