promise

Promise()講解

Promise對象

Promise是一個構造函數

自己身上有all、reject、resolve這幾個眼熟的方法,

原型上有then、catch等同樣很眼熟的方法。這么說用Promise new出來的對象肯定就有then、catch方法嘍,沒錯

var p = new Promise(function(resolve,reject){

? ? //做一些異步操作

? ? setTimeout(function(){

? ? ? ? console.log('執行完成');

? ? ? ? resolve('隨便什么數據');

? ? },2000);

});

Promise的構造函數接收一個參數,是函數,并且傳入兩個參數:resolve,reject,分別表示異步操作執行成功后的回調函數和異步操作執行失敗后的回調函數。其實這里用“成功”和“失敗”來描述并不準確,按照標準來講,resolve是將Promise的狀態置為fullfiled,reject是將Promise的狀態置為rejected。不過在我們開始階段可以先這么理解,后面再細究概念。

在上面的代碼中,我們執行了一個異步操作,也就是setTimeout,2秒后,輸出“執行完成”,并且調用resolve方法。

function runAsync(){

? ? var p = new Promise(function(resolve,reject){

? ? ? ? //做一些異步操作

? ? ? ? setTimeout(function(){

? ? ? ? ? ? console.log('執行完成');

? ? ? ? ? ? resolve('隨便什么數據');

? ? ? ? },2000);

? ? });

? ? return p;? ? ? ? ? ?

}

runAsync()

這時候你應該有兩個疑問:1.包裝這么一個函數有毛線用?2.resolve(‘隨便什么數據’);這是干毛的?

我們繼續來講。在我們包裝好的函數最后,會return出Promise對象,也就是說,執行這個函數我們得到了一個Promise對象。還記得Promise對象上有then、catch方法吧?這就是強大之處了,看下面的代碼:

runAsync().then(function(data){

? ? console.log(data);

? ? //后面可以用傳過來的數據做些其他操作

? ? //......

});

這時候你應該有所領悟了,原來then里面的函數就跟我們平時的回調函數一個意思,能夠在runAsync這個異步任務執行完成之后被執行。這就是Promise的作用了,簡單來講,就是能把原來的回調寫法分離出來,在異步操作執行完后,用鏈式調用的方式執行回調函數

鏈式操作的用法

所以,從表面上看,Promise只是能夠簡化層層回調的寫法,而實質上,Promise的精髓是“狀態”,用維護狀態、傳遞狀態的方式來使得回調函數能夠及時調用,它比傳遞callback函數要簡單、靈活的多。所以使用Promise的正確場景是這樣的:

runAsync1()

.then(function(data){

? ? console.log(data);

? ? return runAsync2();

})

.then(function(data){

? ? console.log(data);

? ? return runAsync3();

})

.then(function(data){

? ? console.log(data);

});

reject的用法

到這里,你應該對“Promise是什么玩意”有了最基本的了解。那么我們接著來看看ES6的Promise還有哪些功能。我們光用了resolve,還沒用reject呢,它是做什么的呢?事實上,我們前面的例子都是只有“執行成功”的回調,還沒有“失敗”的情況,reject的作用就是把Promise的狀態置為rejected,這樣我們在then中就能捕捉到,然后執行“失敗”情況的回調??聪旅娴拇a。

function getNumber(){

? ? var p = new Promise(function(resolve,reject){

? ? ? ? //做一些異步操作

? ? ? ? setTimeout(function(){

? ? ? ? ? ? var num = Math.ceil(Math.random()*10);//生成1-10的隨機數

? ? ? ? ? ? if(num<=5){

? ? ? ? ? ? ? ? resolve(num);

? ? ? ? ? ? }

? ? ? ? ? ? else{

? ? ? ? ? ? ? ? reject('數字太大了');

? ? ? ? ? ? }

? ? ? ? },2000);

? ? });

? ? return p;? ? ? ? ? ?

}

getNumber()

.then(

? ? function(data){

? ? ? ? console.log('resolved');

? ? ? ? console.log(data);

? ? },?

? ? function(reason,data){

? ? ? ? console.log('rejected');

? ? ? ? console.log(reason);

? ? }

);

catch的用法

我們知道Promise對象除了then方法,還有一個catch方法,它是做什么用的呢?其實它和then的第二個參數一樣,用來指定reject的回調,用法是這樣:

getNumber()

.then(function(data){

? ? console.log('resolved');

? ? console.log(data);

})

.catch(function(reason){

? ? console.log('rejected');

? ? console.log(reason);

});

也就是說進到catch方法里面去了,而且把錯誤原因傳到了reason參數中。即便是有錯誤的代碼也不會報錯了,這與我們的try/catch語句有相同的功能。

all的用法

Promise的all方法提供了并行執行異步操作的能力,并且在所有異步操作執行完后才執行回調。我們仍舊使用上面定義好的runAsync1、runAsync2、runAsync3這三個函數,看下面的例子:

Promise

.all([runAsync1(),runAsync2(),runAsync3()])

.then(function(results){

? ? console.log(results);

});

用Promise.all來執行,all接收一個數組參數,里面的值最終都算返回Promise對象。這樣,三個異步操作的并行執行的,等到它們都執行完后才會進到then里面。那么,三個異步操作返回的數據哪里去了呢?都在then里面呢,all會把所有異步操作的結果放進一個數組中傳給then,就是上面的results

有了all,你就可以并行執行多個異步操作,并且在一個回調中處理所有的返回數據,是不是很酷?有一個場景是很適合用這個的,一些游戲類的素材比較多的應用,打開網頁時,預先加載需要用到的各種資源如圖片、flash以及各種靜態文件。所有的都加載完后,我們再進行頁面的初始化。

race的用法

all方法的效果實際上是「誰跑的慢,以誰為準執行回調」,那么相對的就有另一個方法「誰跑的快,以誰為準執行回調」,這就是race方法,這個詞本來就是賽跑的意思。race的用法與all一樣,我們把上面runAsync1的延時改為1秒來看一下

Promise

.race([runAsync1(),runAsync2(),runAsync3()])

.then(function(results){

? ? console.log(results);

});

這三個異步操作同樣是并行執行的。結果你應該可以猜到,1秒后runAsync1已經執行完了,此時then里面的就執行了。結果是這樣的:?

這個race有什么用呢?

requestImg函數會異步請求一張圖片,我把地址寫為”xxxxxx”,所以肯定是無法成功請求到的。timeout函數是一個延時5秒的異步操作。我們把這兩個返回Promise對象的函數放進race,于是他倆就會賽跑,如果5秒之內圖片請求成功了,那么遍進入then方法,執行正常的流程。如果5秒鐘圖片還未成功返回,那么timeout就跑贏了,則進入catch,報出“圖片請求超時”的信息

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,106評論 6 542
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,441評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,211評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,736評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,475評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,834評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,829評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,009評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,559評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,306評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,516評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,038評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,728評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,132評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,443評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,249評論 3 399
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,484評論 2 379

推薦閱讀更多精彩內容

  • 本文適用的讀者 本文寫給有一定Promise使用經驗的人,如果你還沒有使用過Promise,這篇文章可能不適合你,...
    HZ充電大喵閱讀 7,322評論 6 19
  • 特點 Promise能將回調分離出來,在異步操作執行之后,用鏈式方法執行回調,雖然es5用封裝函數也能實現,但是如...
    一二三kkxx閱讀 629評論 0 1
  • //本文內容起初摘抄于 阮一峰 作者的譯文,用于記錄和學習,建議觀者移步于原文 概念: 所謂的Promise,...
    曾經過往閱讀 1,246評論 0 7
  • 去年6月份, ES2015正式發布(也就是ES6,ES6是它的乳名),其中Promise被列為正式規范。作為ES6...
    豬豬俠闖天下閱讀 949評論 0 0
  • 去年6月份, ES2015正式發布(也就是ES6,ES6是它的乳名),其中Promise被列為正式規范。作為ES6...
    yzc123446閱讀 295評論 0 1