promise 快速入門

Promise 的含義

Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大。它由社區(qū)最早提出和實現(xiàn),ES6 將其寫進了語言標準,統(tǒng)一了用法,原生提供了Promise對象。

Promise對象有以下兩個特點。

(1)對象的狀態(tài)不受外界影響。Promise對象代表一個異步操作,有三種狀態(tài):pending(進行中)、fulfilled(已成功)和rejected(已失?。V挥挟惒讲僮鞯慕Y(jié)果,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)。

(2)一旦狀態(tài)改變,就不會再變,任何時候都可以得到這個結(jié)果。Promise對象的狀態(tài)改變,只有兩種可能:從pending變?yōu)?code>fulfilled和從pending變?yōu)?code>rejected。只要這兩種情況發(fā)生,狀態(tài)就凝固了,不會再變了,會一直保持這個結(jié)果,這時就稱為 resolved(已定型)。如果改變已經(jīng)發(fā)生了,你再對Promise對象添加回調(diào)函數(shù),也會立即得到這個結(jié)果。這與事件(Event)完全不同,事件的特點是,如果你錯過了它,再去監(jiān)聽,是得不到結(jié)果的。

基本用法

// resolve, reject 由 js 引擎部署
const p = new Promise((resolve, reject) => {
    console.log('yo.')
    // some code
 
    // 是當(dāng)前的 Promise 對象的狀態(tài)從 'pending' 變?yōu)?'resolved' 成功
    // 并且不再改變
    resolve('hello resovle')
    // reject 讓狀態(tài)從 'pending' 變?yōu)?'reject' 失敗
    // reject(err)
})
// Promise 內(nèi)部的代碼,會在 new 的時候立即執(zhí)行

// Promise 狀態(tài)為 resolve 時,執(zhí)行 then()
p.then((value) => {
    // resolve 會把他的參數(shù)傳給 then()
    console.log(value) // 'hello resolve'
})
.catch((err) => {
    // 在 Promise 狀態(tài)為 reject 時執(zhí)行
    // 或 前面的 then() 發(fā)生錯誤時執(zhí)行
    console.log(err)
})

方法精講

Promise 的常用 API 如下:

  • Promise.resolve(value)

類方法,該方法返回一個以 value 值解析后的 Promise 對象 1、如果這個值是個 thenable(即帶有 then 方法),返回的 Promise 對象會“跟隨”這個 thenable 的對象,采用它的最終狀態(tài)(指 resolved/rejected/pending/settled)
2、如果傳入的 value 本身就是 Promise 對象,則該對象作為 Promise.resolve 方法的返回值返回。
3、其他情況以該值為成功狀態(tài)返回一個 Promise 對象。

上面是 resolve 方法的解釋,傳入不同類型的 value 值,返回結(jié)果也有區(qū)別。這個 API 比較重要,建議大家通過練習(xí)一些小例子,并且配合上面的解釋來熟悉它。如下幾個小例子:

//如果傳入的 value 本身就是 Promise 對象,則該對象作為 Promise.resolve 方法的返回值返回。  
function fn(resolve){
    setTimeout(function(){
        resolve(123);
    },3000);
}
let p0 = new Promise(fn);
let p1 = Promise.resolve(p0);
// 返回為true,返回的 Promise 即是 入?yún)⒌?Promise 對象。
console.log(p0 === p1);
復(fù)制代碼

傳入 thenable 對象,返回 Promise 對象跟隨 thenable 對象的最終狀態(tài)。

ES6 Promises 里提到了 Thenable 這個概念,簡單來說它就是一個非常類似 Promise 的東西。最簡單的例子就是 jQuery.ajax,它的返回值就是 thenable 對象。但是要謹記,并不是只要實現(xiàn)了 then 方法就一定能作為 Promise 對象來使用。

//如果傳入的 value 本身就是 thenable 對象,返回的 promise 對象會跟隨 thenable 對象的狀態(tài)。
let promise = Promise.resolve($.ajax('/test/test.json'));// => promise對象
promise.then(function(value){
   console.log(value);
});
復(fù)制代碼

返回一個狀態(tài)已變成 resolved 的 Promise 對象。

let p1 = Promise.resolve(123); 
//打印p1 可以看到p1是一個狀態(tài)置為resolved的Promise對象
console.log(p1)
復(fù)制代碼
  • Promise.reject

類方法,且與 resolve 唯一的不同是,返回的 promise 對象的狀態(tài)為 rejected。

  • Promise.prototype.then

實例方法,為 Promise 注冊回調(diào)函數(shù),函數(shù)形式:fn(vlaue){},value 是上一個任務(wù)的返回結(jié)果,then 中的函數(shù)一定要 return 一個結(jié)果或者一個新的 Promise 對象,才可以讓之后的then 回調(diào)接收。

  • Promise.prototype.catch

實例方法,捕獲異常,函數(shù)形式:fn(err){}, err 是 catch 注冊 之前的回調(diào)拋出的異常信息。

  • Promise.race

類方法,多個 Promise 任務(wù)同時執(zhí)行,返回最先執(zhí)行結(jié)束的 Promise 任務(wù)的結(jié)果,不管這個 Promise 結(jié)果是成功還是失敗。 。

  • Promise.all

類方法,多個 Promise 任務(wù)同時執(zhí)行。
如果全部成功執(zhí)行,則以數(shù)組的方式返回所有 Promise 任務(wù)的執(zhí)行結(jié)果。 如果有一個 Promise 任務(wù) rejected,則只返回 rejected 任務(wù)的結(jié)果。


方法詳解

Promise.prototype.then()

Promise 實例具有then方法,也就是說,then方法是定義在原型對象Promise.prototype上的。它的作用是為 Promise 實例添加狀態(tài)改變時的回調(diào)函數(shù)。前面說過,then方法的第一個參數(shù)是resolved狀態(tài)的回調(diào)函數(shù),第二個參數(shù)(可選)是rejected狀態(tài)的回調(diào)函數(shù)。then方法返回的是一個新的Promise實例(注意,不是原來那個Promise實例)。因此可以采用鏈式寫法,即then方法后面再調(diào)用另一個then方法。

p.then(val => {
    return val
    // return val 會讓 val 作為 下一個 then() 的參數(shù)
}).then(val => {
    console.log(val)
}).then(...)

Promise.prototype.catch()

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

p(val).then(() => {
  // ...
}).catch((err) => {
  // 處理 p(val) 和 前一個回調(diào)函數(shù)運行時發(fā)生的錯誤
  console.log('發(fā)生錯誤!', err)
})

Promise.prototype.finally()

finally方法用于指定不管 Promise 對象最后狀態(tài)如何,都會執(zhí)行的操作。該方法是 ES2018 引入標準的。

promise
.then(result => {···})
.catch(error => {···})
.finally(() => {···});

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

Promise.all()

Promise.all方法用于將多個 Promise 實例,包裝成一個新的 Promise 實例。

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

上面代碼中,Promise.all方法接受一個數(shù)組作為參數(shù),p1p2、p3都是 Promise 實例,如果不是,就會先調(diào)用下面講到的Promise.resolve方法,將參數(shù)轉(zhuǎn)為 Promise 實例,再進一步處理。(Promise.all方法的參數(shù)可以不是數(shù)組,但必須具有 Iterator 接口,且返回的每個成員都是 Promise 實例。)

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

(1)只有p1、p2p3的狀態(tài)都變成fulfilled,p的狀態(tài)才會變成fulfilled,此時p1、p2、p3的返回值組成一個數(shù)組,傳遞給p的回調(diào)函數(shù)。

(2)只要p1、p2p3之中有一個被rejected,p的狀態(tài)就變成rejected,此時第一個被reject的實例的返回值,會傳遞給p的回調(diào)函數(shù)。

Promise.race()

類似 Promise.all(), 區(qū)別在于 下面代碼中,只要p1p2、p3之中有一個實例率先改變狀態(tài),p的狀態(tài)就跟著改變。那個率先改變的 Promise 實例的返回值,就傳遞給p的回調(diào)函數(shù)。

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

參考 阮一峰 ES6/promise

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容