ES6:理解Promise

1、Promise

Promise以前擂找,在需要多個(gè)異步操作的時(shí)候,會(huì)導(dǎo)致多個(gè)回調(diào)函數(shù)嵌套浩销,導(dǎo)致代碼不夠直觀贯涎,就是常說的回調(diào)地獄。

aFunc(function(aRes) {
  bFunc(aRes, function(bRes) {
    cFunc(bRes, function(cRes) {
      console.log('得到最終結(jié)果: ' + cRes);
    }, callback);
  }, callback);
}, callback);

通常通過 Promise 來解決慢洋,Promise本意是承諾塘雳,在程序中的意思就是承諾我過一段時(shí)間后會(huì)給你一個(gè)結(jié)果陆盘。 什么時(shí)候會(huì)用到過一段時(shí)間?答案是異步操作败明,異步是指可能比較長時(shí)間才有結(jié)果的才做隘马,例如網(wǎng)絡(luò)請(qǐng)求、讀取本地文件等妻顶。

aFunc().then(function(aRes) {
  return bFunc(aRes);
})
.then(function(bRes) {
  return cFunc(bRes);
})
.then(function(cRes) {
  console.log('得到最終結(jié)果: ' + cRes);
})
.catch(callback);
1.1酸员、Promise狀態(tài)

Promise 必須為以下三種狀態(tài)之一:等待態(tài)(Pending)、執(zhí)行態(tài)(Fulfilled)和拒絕態(tài)(Rejected)讳嘱。一旦Promise 被 resolve 或 reject幔嗦,不能再遷移至其他任何狀態(tài)(即狀態(tài) immutable)。

1.2沥潭、Promise過程
  1. 初始化 Promise 狀態(tài)(pending)
  2. 立即執(zhí)行 Promise 中傳入的 fn 函數(shù)邀泉,將 Promise 內(nèi)部 resolve、reject 函數(shù)作為參數(shù)傳遞給 fn 钝鸽,按事件機(jī)制時(shí)機(jī)處理
  3. 執(zhí)行 then(..) 注冊回調(diào)處理數(shù)組(then 方法可被同一個(gè) promise 調(diào)用多次)
  4. Promise 里的關(guān)鍵是要保證汇恤,then方法傳入的參數(shù) onFulfilled 和 onRejected,必須在then方法被調(diào)用的那一輪事件循環(huán)之后的新執(zhí)行棧中執(zhí)行拔恰。

2屁置、Promise用法

Promise對(duì)象是一個(gè)構(gòu)造函數(shù),用來生成Promise實(shí)例仁连。

const promise = new Promise(function(resolve, reject) {
    // ... some code

    if (/* 異步操作成功 */){
        resolve(value);
    } else {
        reject(error);
    }
});

Promise構(gòu)造函數(shù)接受一個(gè)函數(shù)作為參數(shù)蓝角,該函數(shù)的兩個(gè)參數(shù)分別是resolvereject

  • resolve函數(shù)的作用是,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤俺晒Α?/li>
  • reject函數(shù)的作用是饭冬,將Promise對(duì)象的狀態(tài)從“未完成”變?yōu)椤笆 ?/li>

3使鹅、Promise對(duì)象之實(shí)例方法

3.1、Promise.prototype.then()

Promise 實(shí)例具有 then 方法昌抠,也就是說患朱,then方法是定義在原型對(duì)象Promise.prototype 上的。它的作用是為 Promise 實(shí)例添加狀態(tài)改變時(shí)的回調(diào)函數(shù)炊苫。前面說過裁厅, then 方法的第一個(gè)參數(shù)是 resolved 狀態(tài)對(duì)應(yīng)的回調(diào)函數(shù), 第二個(gè)參數(shù)(可選) 是 rejected 狀態(tài)對(duì)應(yīng)的回調(diào)函數(shù)。

3.2侨艾、Promise.prototype.catch()

Promise.prototype.catch() 方法是 .then(null,rejection).then(undefined,rejection) 的別名执虹,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。

getJSON('/posts.json').then(function(posts) {
  // ...
}).catch(function(error) {
  // 處理 getJSON 和 前一個(gè)回調(diào)函數(shù)運(yùn)行時(shí)發(fā)生的錯(cuò)誤
  console.log('發(fā)生錯(cuò)誤唠梨!', error);
});

上面代碼中袋励,getJSON()方法返回一個(gè) Promise 對(duì)象,如果該對(duì)象狀態(tài)變?yōu)?code>resolved,則會(huì)調(diào)用then()方法指定的回調(diào)函數(shù)茬故;如果異步操作拋出錯(cuò)誤盖灸,狀態(tài)就會(huì)變?yōu)?code>rejected,就會(huì)調(diào)用catch()方法指定的回調(diào)函數(shù)磺芭,處理這個(gè)錯(cuò)誤赁炎。另外,then()方法指定的回調(diào)函數(shù)钾腺,如果運(yùn)行中拋出錯(cuò)誤徙垫,也會(huì)被catch()方法捕獲。

3.3垮庐、Promise.prototype.finally()

finally()方法用于指定不管 Promise 對(duì)象最后狀態(tài)如何松邪,都會(huì)執(zhí)行的操作坞琴。

getJSON('/posts.json').
    .then(result => {···})
    .catch(error => {···})
    .finally(() => {···});

上面代碼中哨查,不管promise最后的狀態(tài),在執(zhí)行完thencatch指定的回調(diào)函數(shù)以后剧辐,都會(huì)執(zhí)行finally方法指定的回調(diào)函數(shù)寒亥。

3.4、Promise.all()

Promise.all() 方法用于將多個(gè) Promise 實(shí)例荧关,包裝成一個(gè)新的 Promise 實(shí)例溉奕。

const p = Promise.all([p1, p2, p3]);

上面代碼中,Promise.all()方法接受一個(gè)數(shù)組作為參數(shù)忍啤,p1加勤、p2p3都是 Promise 實(shí)例同波,如果不是鳄梅,就會(huì)先調(diào)用下面講到的Promise.resolve方法,將參數(shù)轉(zhuǎn)為 Promise 實(shí)例未檩,再進(jìn)一步處理戴尸。另外,Promise.all()方法的參數(shù)可以不是數(shù)組冤狡,但必須具有 Iterator 接口孙蒙,且返回的每個(gè)成員都是 Promise 實(shí)例。

p的狀態(tài)由p1悲雳、p2挎峦、p3決定,分成兩種情況合瓢。

(1)只有p1浑测、p2p3的狀態(tài)都變成fulfilledp的狀態(tài)才會(huì)變成fulfilled迁央,此時(shí)p1掷匠、p2p3的返回值組成一個(gè)數(shù)組岖圈,傳遞給p的回調(diào)函數(shù)讹语。

(2)只要p1p2蜂科、p3之中有一個(gè)被rejected顽决,p的狀態(tài)就變成rejected,此時(shí)第一個(gè)被reject的實(shí)例的返回值导匣,會(huì)傳遞給p的回調(diào)函數(shù)才菠。

3.5、Promise.race()

Promise.race()方法同樣是將多個(gè) Promise 實(shí)例贡定,包裝成一個(gè)新的 Promise 實(shí)例赋访。

const p = Promise.all([p1, p2, p3]);

上面代碼中,只要p1缓待、p2蚓耽、p3之中有一個(gè)實(shí)例率先改變狀態(tài),p的狀態(tài)就跟著改變旋炒。那個(gè)率先改變的 Promise 實(shí)例的返回值步悠,就傳遞給p的回調(diào)函數(shù)。

4瘫镇、Promise使用場景

  • 將圖片的加載寫成一個(gè)Promise鼎兽,一旦加載完成,Promise的狀態(tài)就發(fā)生變化
const preloadImage = function (path) {
    return new Promise(function (resolve, reject) {
        const image = new Image();
        image.onload  = resolve;
        image.onerror = reject;
        image.src = path;
    });
};
  • 通過鏈?zhǔn)讲僮飨吵瑢⒍鄠€(gè)渲染數(shù)據(jù)分別給個(gè)then谚咬,讓其各自處理數(shù)據(jù)⊥酰或當(dāng)下個(gè)異步請(qǐng)求依賴上個(gè)請(qǐng)求結(jié)果的時(shí)候序宦,我們也能夠通過鏈?zhǔn)讲僮饔押媒鉀Q問題
getData().then(res=>{
    let { bannerList } = res
    console.log(bannerList)
    return res
}).then(res=>{
    let { storeList } = res
    console.log(storeList)
    return res
}).then(res=>{
    let { categoryList } = res
    console.log(categoryList)
    return res
})
  • 通過all()實(shí)現(xiàn)多個(gè)請(qǐng)求合并在一起,匯總所有請(qǐng)求結(jié)果
function initLoad(){
    // loading.show()
    Promise.all([getBannerList(),getStoreList(),getCategoryList()]).then(res=>{
        console.log(res)
        loading.hide()
    }).catch(err=>{
        console.log(err)
        loading.hide()
    })
}
//數(shù)據(jù)初始化    
initLoad()
  • 通過race可以設(shè)置圖片請(qǐng)求超時(shí)
function requestImg(){
    var p = new Promise(function(resolve, reject){
        var img = new Image();
        img.onload = function(){
           resolve(img);
        }
        //img.src = "xx.jpg"; 正確的
        img.src = "xxx.jpggg";  // 錯(cuò)誤的
    });
    return p;
}

//延時(shí)函數(shù)背苦,用于給請(qǐng)求計(jì)時(shí)
function timeout(){
    var p = new Promise(function(resolve, reject){
        setTimeout(function(){
            reject('圖片請(qǐng)求超時(shí)');
        }, 5000);
    });
    return p;
}

Promise
  .race([requestImg(), timeout()])
  .then(function(results){
      console.log(results);
  })
  .catch(function(reason){
      console.log(reason);
  });
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末互捌,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子行剂,更是在濱河造成了極大的恐慌秕噪,老刑警劉巖,帶你破解...
    沈念sama閱讀 210,914評(píng)論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件厚宰,死亡現(xiàn)場離奇詭異腌巾,居然都是意外死亡遂填,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 89,935評(píng)論 2 383
  • 文/潘曉璐 我一進(jìn)店門澈蝙,熙熙樓的掌柜王于貴愁眉苦臉地迎上來吓坚,“玉大人,你說我怎么就攤上這事灯荧〗富鳎” “怎么了?”我有些...
    開封第一講書人閱讀 156,531評(píng)論 0 345
  • 文/不壞的土叔 我叫張陵逗载,是天一觀的道長哆窿。 經(jīng)常有香客問我,道長厉斟,這世上最難降的妖魔是什么挚躯? 我笑而不...
    開封第一講書人閱讀 56,309評(píng)論 1 282
  • 正文 為了忘掉前任,我火速辦了婚禮擦秽,結(jié)果婚禮上码荔,老公的妹妹穿的比我還像新娘。我一直安慰自己号涯,他們只是感情好目胡,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,381評(píng)論 5 384
  • 文/花漫 我一把揭開白布锯七。 她就那樣靜靜地躺著链快,像睡著了一般。 火紅的嫁衣襯著肌膚如雪眉尸。 梳的紋絲不亂的頭發(fā)上域蜗,一...
    開封第一講書人閱讀 49,730評(píng)論 1 289
  • 那天,我揣著相機(jī)與錄音噪猾,去河邊找鬼霉祸。 笑死,一個(gè)胖子當(dāng)著我的面吹牛袱蜡,可吹牛的內(nèi)容都是我干的丝蹭。 我是一名探鬼主播,決...
    沈念sama閱讀 38,882評(píng)論 3 404
  • 文/蒼蘭香墨 我猛地睜開眼坪蚁,長吁一口氣:“原來是場噩夢啊……” “哼奔穿!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起敏晤,我...
    開封第一講書人閱讀 37,643評(píng)論 0 266
  • 序言:老撾萬榮一對(duì)情侶失蹤贱田,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后嘴脾,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體男摧,經(jīng)...
    沈念sama閱讀 44,095評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,448評(píng)論 2 325
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了耗拓。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拇颅。...
    茶點(diǎn)故事閱讀 38,566評(píng)論 1 339
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖乔询,靈堂內(nèi)的尸體忽然破棺而出蔬蕊,到底是詐尸還是另有隱情,我是刑警寧澤哥谷,帶...
    沈念sama閱讀 34,253評(píng)論 4 328
  • 正文 年R本政府宣布岸夯,位于F島的核電站,受9級(jí)特大地震影響们妥,放射性物質(zhì)發(fā)生泄漏猜扮。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,829評(píng)論 3 312
  • 文/蒙蒙 一监婶、第九天 我趴在偏房一處隱蔽的房頂上張望旅赢。 院中可真熱鬧,春花似錦惑惶、人聲如沸煮盼。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,715評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽僵控。三九已至,卻和暖如春鱼冀,著一層夾襖步出監(jiān)牢的瞬間报破,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,945評(píng)論 1 264
  • 我被黑心中介騙來泰國打工千绪, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留充易,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,248評(píng)論 2 360
  • 正文 我出身青樓荸型,卻偏偏與公主長得像盹靴,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子瑞妇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,440評(píng)論 2 348

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

  • 什么是Promise Promise是異步編程的一種解決方案稿静,比傳統(tǒng)的異步解決方案【回調(diào)函數(shù)】和【事件】更合理、更...
    前端的爬行之旅閱讀 290評(píng)論 0 0
  • Promise對(duì)象的含義 所謂的Promise就是一個(gè)對(duì)象踪宠,用來傳遞異步操作的消息自赔,它代表某個(gè)未來才會(huì)知道結(jié)果的事...
    萘小蒽閱讀 304評(píng)論 0 0
  • 簡介 ES6中除了上篇文章講過的語法新特性和一些新的API之外,還有兩個(gè)非常重要的新特性就是Promise和Gen...
    flydean程序那些事閱讀 1,376評(píng)論 0 2
  • 原創(chuàng)文章&經(jīng)驗(yàn)總結(jié)&從校招到A廠一路陽光一路滄桑 詳情請(qǐng)戳www.codercc.com 主要知識(shí)點(diǎn):Promis...
    你聽___閱讀 4,243評(píng)論 0 7
  • Promiese 簡單說就是一個(gè)容器柳琢,里面保存著某個(gè)未來才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果绍妨,語法上說润脸,Pr...
    雨飛飛雨閱讀 3,352評(píng)論 0 19