ES6 Promise 對(duì)象

在 MDN 中對(duì) Promise 的定義是:Promise 對(duì)象用于表示一個(gè)異步操作的最終狀態(tài)(完成或失斄菩濉)线召,以及其返回的值。

Promise 對(duì)象存在以下三種狀態(tài):

  • pending: 初始狀態(tài)多矮;
  • fulfilled:成功狀態(tài)缓淹;
  • rejected:失敗狀態(tài);

Promise 對(duì)象的初始狀態(tài)是 pending塔逃,最終狀態(tài)是 fulfilled 或者 rejected讯壶,其中 fulfilled 表示成功狀態(tài),rejected 表示失敗狀態(tài)湾盗。狀態(tài)只能夠由 pending 變成 fulfilled 或 rejected鹏溯,當(dāng) Promise 對(duì)象的狀態(tài)改變后就不可以再改變了。

Promise 狀態(tài)改變

Promise 簡(jiǎn)單的使用方式如下

let pro = new Promise((resolve, reject) => {
  // 執(zhí)行異步操作代碼
  // 異步操作成功淹仑,則 resolve(value)
  // 異步操作失敗丙挽,則 reject(error)
});

從上面的使用方式來(lái)看,我們可以知道 Promise 是一個(gè)構(gòu)造函數(shù)匀借,其參數(shù)接受一個(gè)匿名函數(shù)颜阐,該匿名函數(shù)有兩個(gè)參數(shù),分別是 resolve 和 reject 函數(shù)吓肋。

通過(guò) new Promise 得到一個(gè) Promise 對(duì)象凳怨,Promise 構(gòu)造函數(shù)所接受的匿名函數(shù)會(huì)直接執(zhí)行,一般是在里面執(zhí)行異步操作是鬼。

當(dāng)異步操作成功的時(shí)候肤舞,執(zhí)行 resolve 函數(shù),會(huì)把 Promise 對(duì)象的狀態(tài)由 pending 變?yōu)?fulfilled均蜜;當(dāng)異步操作失敗的時(shí)候李剖,執(zhí)行 reject 函數(shù),會(huì)把 Promise 對(duì)象的狀態(tài)由 pending 變?yōu)?rejected囤耳。其中 resolve 和 reject 函數(shù)都分別傳入了返回值(value)和錯(cuò)誤值(error)篙顺,這兩個(gè)值將會(huì)作為 Promise 對(duì)象 then 方法的兩個(gè)回調(diào)函數(shù)的實(shí)參。

Promise 對(duì)象上具有很多方法充择,其方法是掛載在對(duì)應(yīng)的原型即 Promise.prototype 上面的德玫,下面就 Promise 對(duì)象的方法做一個(gè)詳細(xì)的介紹。

Promise.prototype.then(onFulfilled, onRejected)

當(dāng) Promise 對(duì)象的狀態(tài)由 pending 變?yōu)?fulfilled 或 rejected 的時(shí)候椎麦,會(huì)觸發(fā) Promise 對(duì)象的 then 方法宰僧。

pro.then((value) => {
  // fulfilled
}, (error) => {
  // rejected
});

then 方法接受兩個(gè)回調(diào)函數(shù)作為參數(shù),當(dāng) Promise 對(duì)象當(dāng)狀態(tài)由 pending 變?yōu)?fulfilled 的時(shí)候观挎,執(zhí)行第一個(gè)回調(diào)函數(shù)琴儿;當(dāng) Promise 對(duì)象當(dāng)狀態(tài)由 pending 變?yōu)?rejected 的時(shí)候查刻,執(zhí)行第二個(gè)回調(diào)函數(shù)(可選)。這兩個(gè)回調(diào)函數(shù)的參數(shù)分別是執(zhí)行 resolve 和 reject 函數(shù)時(shí)傳入的值凤类。

舉個(gè)簡(jiǎn)單的例子

let timeoutPro = new Promise((resolve, reject) => {
  setTimeout(resolve, 1000, 'resolve');
});
timeoutPro.then((value) => {
  console.log(value);
});

我們還可以將其封裝起來(lái)

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'resolve');
  });
}
timeout(1000).then((value) => {
  console.log(value);
});

下面是一個(gè)用 Promise對(duì)象實(shí)現(xiàn)的 Ajax 操作的例子

let get = function (url) {
  return new Promise((resolve, reject) => {
    let xhr = new XMLHttpRequest();
    xhr.open("GET", url);
    xhr.responseType = "json";
    xhr.setRequestHeader("Accept", "application/json");
    xhr.send();
    xhr.onreadystatechange = () => {
      if (xhr.readyState != 4) return;
      if (xhr.status == 200) {
        resolve(xhr.response);
      } else {
        reject(xhr.statusText);
      }
    };
  });
};
get("0010.json").then((res) => {
  console.log(res.name);  // ttsy
}, (error) => {
  console.log(error);
});

注:這里 0010.json 為一個(gè)與存放上述代碼的腳本文件同目錄的一個(gè) json 文件,里面的內(nèi)容如下

{
  "name":"ttsy",
  "age":25
}

then 方法返回的是一個(gè)新的 Promise 對(duì)象普气。因此可以采用鏈?zhǔn)綄?xiě)法谜疤,即 then 方法后面再調(diào)用另一個(gè) then 方法。而下一個(gè) then 方法的行為跟前一個(gè) then 方法的返回值有關(guān)现诀。

  • 如果上一個(gè) then 中的回調(diào)函數(shù)返回一個(gè)值夷磕,那么該 then 返回的 Promise 對(duì)象將會(huì)成為 fulfilled 狀態(tài),并且上一個(gè) then 的回調(diào)函數(shù)返回的值將作為下一個(gè) then 的回調(diào)函數(shù)的參數(shù)值仔沿;
  • 如果上一個(gè) then 中的回調(diào)函數(shù)拋出一個(gè)錯(cuò)誤坐桩,那么該 then 返回的 Promise 對(duì)象將會(huì)成為 rejected 狀態(tài),并且上一個(gè) then 的回調(diào)函數(shù)拋出的錯(cuò)誤將作為下一個(gè) then 的回調(diào)函數(shù)的參數(shù)值封锉;
  • 如果上一個(gè) then 中的回調(diào)函數(shù)返回一個(gè) Promise 對(duì)象绵跷,那么下一個(gè) then 則會(huì)根據(jù)返回的 Promise 對(duì)象的狀態(tài)變化來(lái)執(zhí)行。

舉個(gè)例子~

當(dāng)上一個(gè) then 中的回調(diào)函數(shù)返回一個(gè)值時(shí)

timeout(1000).then((value) => {
  return value;
}).then((value) => {
  console.log(value);  // resolve
})

當(dāng)上一個(gè) then 中的回調(diào)函數(shù)拋出一個(gè)錯(cuò)誤時(shí)

timeout(1000).then((value) => {
  throw 'error'
}).then((value) => {
  console.log(value);
}, (error) => {
  console.log(error)  // error
})

當(dāng)上一個(gè) then 中的回調(diào)函數(shù)返回一個(gè) Promise 對(duì)象時(shí)

timeout(1000).then((value) => {
  return timeout(1000);
}).then((value) => {
  console.log(value);  // resolve
}, (error) => {
  console.log(error)
})

一般來(lái)講成福,在 then 中的回調(diào)函數(shù)返回一個(gè) Promise 對(duì)象的場(chǎng)景都是 http 請(qǐng)求的嵌套碾局,上述例子只是為了更方便的表示這種情況,實(shí)際場(chǎng)景中并不會(huì)去這么使用奴艾。

上面說(shuō)的是下一個(gè) then 方法的行為跟前一個(gè) then 方法的返回值有關(guān)净当,但如果一開(kāi)始創(chuàng)建的 Promise 對(duì)象的狀態(tài)由 pending 變?yōu)?rejected 時(shí),又是怎樣的情況呢蕴潦?

function timeoutReject(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(reject, ms, 'reject');
  });
}
timeoutReject(1000).then((value) => {
  console.log(value);
}).then(undefined, (error) => {
  console.log(error)  // error
})

可以看到像啼, Promise 對(duì)象的狀態(tài)變?yōu)槭顟B(tài)時(shí)執(zhí)行第二個(gè) then 中的第二個(gè)回調(diào)函數(shù)的代碼。實(shí)際上潭苞,Promise 對(duì)象的錯(cuò)誤具有「冒泡」性質(zhì)忽冻,會(huì)一直向后傳遞,直到被捕獲為止此疹。

Promise.prototype.catch(onRejected)

Promise.prototype.catch(onRejected) 與 Promise.prototype.then(undefined, onRejected) 是一樣的效果甚颂,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。同樣的秀菱,catch 也返回一個(gè)新的 Promise 對(duì)象振诬。

timeoutReject(1000).then((value) => {
  console.log(value);
}).catch((error) => {
  console.log(error)  // error
})

而在上面說(shuō)到,Promise 對(duì)象的錯(cuò)誤具有「冒泡」性質(zhì)衍菱,會(huì)一直向后傳遞赶么,直到被捕獲為止。所以當(dāng)前面的 Promise 對(duì)象拋出錯(cuò)誤時(shí)脊串,則會(huì)依次冒泡辫呻,直到被 catch 捕獲清钥。

timeoutReject(1000).then((value) => {
  console.log(value);
}).then((value) => {
  console.log(value);
}).catch((error) => {
  console.log(error)  // error
})

上述代碼中,catch 會(huì)捕獲 timeoutReject() 和兩個(gè) then 所返回的 Promise 對(duì)象所拋出的錯(cuò)誤放闺。

一般來(lái)說(shuō)祟昭,不要在 then 方法里面定義 Reject 狀態(tài)的回調(diào)函數(shù)(即 then 的第二個(gè)參數(shù)),總是使用 catch 方法怖侦。

Promise.all()

Promise.all 方法用于將多個(gè) Promise 對(duì)象合成一個(gè) Promise 對(duì)象篡悟,它接受一個(gè)數(shù)組作為參數(shù),數(shù)組中的每一個(gè)元素都是 Promise 對(duì)象匾寝。最終返回一個(gè)新的 Promise 對(duì)象搬葬,其狀態(tài)由傳入的 Promise 對(duì)象共同決定,分為以下兩種情況艳悔。

  • 當(dāng)傳入的 Promise 對(duì)象的狀態(tài)都變成 fulfilled 時(shí)急凰,返回的新的 Promise 對(duì)象的狀態(tài)才會(huì)變成 fulfilled,其 then 方法的回調(diào)函數(shù)的參數(shù)是一個(gè)數(shù)組猜年,分別是傳入的 Promise 對(duì)象的返回值抡锈;
  • 當(dāng)傳入的 Promise 對(duì)象的狀態(tài)其中有一個(gè)變成 rejected 時(shí),返回的新的 Promise 對(duì)象的狀態(tài)就會(huì)變成 rejected乔外,其 then 方法的回調(diào)函數(shù)的參數(shù)是第一個(gè)狀態(tài)變成 reject 的 Promise 對(duì)象的返回值企孩。

傳入的 Promise 對(duì)象的狀態(tài)都變成 fulfilled 時(shí)

function timeout1(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'resolve');
  });
}
function timeout2(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'resolve');
  });
}
Promise.all([timeout1(1000), timeout2(2000)]).then((value) => {
  console.log(value); // [ 'resolve', 'resolve' ]
}).catch((error) => {
  console.log(error)  
})

當(dāng)傳入的 Promise 對(duì)象的狀態(tài)其中有一個(gè)變成 rejected 時(shí)

function timeout(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(resolve, ms, 'resolve');
  });
}
function timeoutReject(ms) {
  return new Promise((resolve, reject) => {
    setTimeout(reject, ms, 'reject');
  });
}
Promise.all([timeout(1000), timeoutReject(2000)]).then((value) => {
  console.log(value); 
}).catch((error) => {
  console.log(error)  // reject
})
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市袁稽,隨后出現(xiàn)的幾起案子勿璃,更是在濱河造成了極大的恐慌,老刑警劉巖推汽,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件补疑,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡歹撒,警方通過(guò)查閱死者的電腦和手機(jī)莲组,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)暖夭,“玉大人锹杈,你說(shuō)我怎么就攤上這事÷踝牛” “怎么了竭望?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)裕菠。 經(jīng)常有香客問(wèn)我咬清,道長(zhǎng),這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任旧烧,我火速辦了婚禮影钉,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘掘剪。我一直安慰自己平委,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布夺谁。 她就那樣靜靜地躺著廉赔,像睡著了一般。 火紅的嫁衣襯著肌膚如雪予权。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天浪册,我揣著相機(jī)與錄音扫腺,去河邊找鬼。 笑死村象,一個(gè)胖子當(dāng)著我的面吹牛笆环,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播厚者,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼躁劣,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了库菲?” 一聲冷哼從身側(cè)響起账忘,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎熙宇,沒(méi)想到半個(gè)月后鳖擒,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡烫止,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年羽嫡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了纺铭。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖蒋川,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情冯遂,我是刑警寧澤拟枚,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站吼渡,受9級(jí)特大地震影響行拢,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一舟奠、第九天 我趴在偏房一處隱蔽的房頂上張望竭缝。 院中可真熱鬧,春花似錦沼瘫、人聲如沸抬纸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)湿故。三九已至,卻和暖如春膜蛔,著一層夾襖步出監(jiān)牢的瞬間坛猪,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工皂股, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留墅茉,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓呜呐,卻偏偏與公主長(zhǎng)得像就斤,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蘑辑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

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

  • Promise的含義: ??Promise是異步編程的一種解決方案洋机,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和...
    呼呼哥閱讀 2,170評(píng)論 0 16
  • 前言 在Promise之前,js的異步編程都是采用回調(diào)函數(shù)和事件的方式洋魂。但是這種編程方式在處理復(fù)雜業(yè)務(wù)的情況下绷旗,很...
    卓三陽(yáng)閱讀 831評(píng)論 0 1
  • 1.Promise 的含義 Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理...
    不可不信緣_b32e閱讀 298評(píng)論 0 1
  • Promise 對(duì)象 Promise 的含義 Promise 是異步編程的一種解決方案副砍,比傳統(tǒng)的解決方案——回調(diào)函...
    neromous閱讀 8,706評(píng)論 1 56
  • “半途而廢”的前瞻性 近日因辦理退休手續(xù)多次到市政務(wù)大廳刁标,井然有序、明亮寬敞的便民窗口讓陷入深深的往事之中址晕;清...
    崇拜范蠡閱讀 250評(píng)論 0 0