ES6 Promise

問題

JavaScript的Callback機(jī)制深入人心俯萎。而ECMAScript的世界同樣充斥的各種異步操作(異步IO皮璧、setTimeout等)版述。異步和Callback的搭載很容易就衍生"回調(diào)金字塔"几蜻≈荆——由此產(chǎn)生Deferred/Promise肮雨。

Deferred起源于Python,后來被CommonJS挖掘并發(fā)揚(yáng)光大归敬,得到了大名鼎鼎的Promise酷含,并且已經(jīng)納入ECMAScript 6(JavaScript下一版本)。

Promise/Deferred是當(dāng)今最著名的異步模型汪茧,不僅強(qiáng)壯了JavaScript Event Loop(事件輪詢)機(jī)制下異步代碼的模型,同時增強(qiáng)了異步代碼的可靠性限番。

有了 Promise 舱污,就可以將異步操作以同步操作的流程表達(dá)出來,避免了層層嵌套的回調(diào)函數(shù)弥虐。此外扩灯,Promise 對象提供統(tǒng)一的接口,使得控制異步操作更加容易霜瘪。

概述

Promise 對象用于延遲(deferred) 計算和異步(asynchronous ) 計算珠插。一個Promise對象代表著一個還未完成,但預(yù)期將來會完成的操作颖对。

語法

    new Promise(executor);
    new Promise(function(resolve, reject) { ... });

例子:
<pre>
var promise = new Promise(function(resolve, reject) {
if (/** 異步操作成功* */){
resolve(value);
} else {
reject(error);
}
});
</br>
promise.then(function(value) {
// success
},
function(value) {
// failure
});
</pre>

參數(shù)

executor帶有 resolve捻撑、reject 兩個參數(shù)的函數(shù)對象。一旦我們的操作完成即可調(diào)用這些函數(shù)缤底。

  • 第一個參數(shù)用在處理執(zhí)行成功的場景
  • 第二個參數(shù)則用在處理執(zhí)行失敗的場景顾患。

描述

Promise對象是一個返回值的代理,這個返回值在promise對象創(chuàng)建時未必已知个唧。它允許你為異步操作的成功或失敗指定處理方法江解。 這使得異步方法可以像同步方法那樣返回值:異步方法會返回一個包含了原返回值的 promise 對象來替代原返回值。

Promise對象有以下幾種狀態(tài):

  • pending: 初始狀態(tài), 非 fulfilled 或 rejected.
  • fulfilled: 成功的操作.
  • rejected: 失敗的操作.

pending狀態(tài)的promise對象既可轉(zhuǎn)換為帶著一個成功值的fulfilled 狀態(tài)徙歼,也可變?yōu)閹е粋€失敗信息的 rejected 狀態(tài)犁河。

特點

  • 對象的狀態(tài)不受外界影響鳖枕,只有異步操作的結(jié)果,可以決定當(dāng)前是哪一種狀態(tài)桨螺,任何其他操作都無法改變這個狀態(tài)耕魄。
    當(dāng)狀態(tài)發(fā)生轉(zhuǎn)換時,promise.then綁定的方法(函數(shù)句柄)就會被調(diào)用彭谁。

  • 一旦狀態(tài)改變吸奴,就不會再變,任何時候都可以得到這個結(jié)果缠局。這與事件(Event)完全不同则奥,事件的特點是,如果你錯過了它狭园,再去監(jiān)聽读处,是得不到結(jié)果的。

當(dāng)綁定方法時唱矛,如果 promise對象已經(jīng)處于 fulfilled 或 rejected 狀態(tài)罚舱,那么相應(yīng)的方法將會被立刻調(diào)用, 所以在異步操作的完成情況和它的綁定方法之間不存在競爭條件绎谦。
因為Promise.prototype.then
Promise.prototype.catch

方法返回 promises對象, 所以它們可以被鏈?zhǔn)秸{(diào)用—— 一種被稱為 composition 的操作管闷。


注意: 如果一個promise對象處在fulfilled或rejected狀態(tài)而不是pending狀態(tài),那么它也可以被稱為
settled
狀態(tài)窃肠。你可能也會聽到一個術(shù)語resolved 包个,它表示promise對象處于settled狀態(tài),或者promise對象被鎖定在了調(diào)用鏈中冤留。關(guān)于promise的狀態(tài)碧囊, Domenic Denicola 的 States and fates 有更多詳情可供參考。

基本的api

  • Promise.resolve()
  • Promise.reject()
  • Promise.prototype.then()
  • Promise.prototype.catch()
  • Promise.all() 完成全部
  • Promise.race() 完成一個

常用的JavaScript的promise的寫法

<pre>
function get(uri){
return http(uri, 'GET', null);
}

</br>

function post(uri,data){
if(typeof data === 'object' && !(data instanceof String || (FormData && data instanceof FormData))) {
var params = [];
for(var p in data) {
if(data[p] instanceof Array) {
for(var i = 0; i < data[p].length; i++) {
params.push(encodeURIComponent(p) + '[]=' + encodeURIComponent(data[p][i]));
}
} else {
params.push(encodeURIComponent(p) + '=' + encodeURIComponent(data[p]));
}
}
data = params.join('&');
}

return http(uri, 'POST', data || null, {
    "Content-type":"application/x-www-form-urlencoded"
});

}
</br>

function http(uri,method,data,headers){
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open(method,uri,true);
if(headers) {
for(var p in headers) {
xhr.setRequestHeader(p, headers[p]);
}
}
xhr.addEventListener('readystatechange',function(e){
if(xhr.readyState === 4) {
if(String(xhr.status).match(/^2\d\d$/)) {
resolve(xhr.responseText);
} else {
reject(xhr);
}
}
});
xhr.send(data);
})
}

</br>

function wait(duration){
return new Promise(function(resolve, reject) {
setTimeout(resolve,duration);
})
}

</br>

function waitFor(element,event,useCapture){
return new Promise(function(resolve, reject) {
element.addEventListener(event,function listener(event){
resolve(event)
this.removeEventListener(event, listener, useCapture);
},useCapture)
})
}

</br>

function loadImage(src) {
return new Promise(function(resolve, reject) {
var image = new Image;
image.addEventListener('load',function listener() {
resolve(image);
this.removeEventListener('load', listener, useCapture);
});
image.src = src;
image.addEventListener('error',reject);
})
}

</br>

function runScript(src) {
return new Promise(function(resolve, reject) {
var script = document.createElement('script');
script.src = src;
script.addEventListener('load',resolve);
script.addEventListener('error',reject);
(document.getElementsByTagName('head')[0] || document.body || document.documentElement).appendChild(script);
})
}

</br>

function domReady() {
return new Promise(function(resolve, reject) {
if(document.readyState === 'complete') {
resolve();
} else {
document.addEventListener('DOMContentLoaded',resolve);
}
})
}
</pre>

兼容性墊片polyfill of the ES6 Promise

es6-promise
es6-promise

參考資料:

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末纤怒,一起剝皮案震驚了整個濱河市糯而,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌泊窘,老刑警劉巖熄驼,帶你破解...
    沈念sama閱讀 216,372評論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異州既,居然都是意外死亡谜洽,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評論 3 392
  • 文/潘曉璐 我一進(jìn)店門吴叶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來阐虚,“玉大人,你說我怎么就攤上這事蚌卤∈凳” “怎么了奥秆?”我有些...
    開封第一講書人閱讀 162,415評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長咸灿。 經(jīng)常有香客問我构订,道長,這世上最難降的妖魔是什么避矢? 我笑而不...
    開封第一講書人閱讀 58,157評論 1 292
  • 正文 為了忘掉前任悼瘾,我火速辦了婚禮,結(jié)果婚禮上审胸,老公的妹妹穿的比我還像新娘亥宿。我一直安慰自己,他們只是感情好砂沛,可當(dāng)我...
    茶點故事閱讀 67,171評論 6 388
  • 文/花漫 我一把揭開白布烫扼。 她就那樣靜靜地躺著,像睡著了一般碍庵。 火紅的嫁衣襯著肌膚如雪映企。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,125評論 1 297
  • 那天静浴,我揣著相機(jī)與錄音堰氓,去河邊找鬼。 笑死马绝,一個胖子當(dāng)著我的面吹牛豆赏,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播富稻,決...
    沈念sama閱讀 40,028評論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼白胀!你這毒婦竟也來了椭赋?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,887評論 0 274
  • 序言:老撾萬榮一對情侶失蹤或杠,失蹤者是張志新(化名)和其女友劉穎哪怔,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體向抢,經(jīng)...
    沈念sama閱讀 45,310評論 1 310
  • 正文 獨居荒郊野嶺守林人離奇死亡认境,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,533評論 2 332
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了挟鸠。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片叉信。...
    茶點故事閱讀 39,690評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖艘希,靈堂內(nèi)的尸體忽然破棺而出硼身,到底是詐尸還是另有隱情硅急,我是刑警寧澤,帶...
    沈念sama閱讀 35,411評論 5 343
  • 正文 年R本政府宣布佳遂,位于F島的核電站营袜,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏丑罪。R本人自食惡果不足惜荚板,卻給世界環(huán)境...
    茶點故事閱讀 41,004評論 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望吩屹。 院中可真熱鬧跪另,春花似錦、人聲如沸祟峦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽宅楞。三九已至针姿,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間厌衙,已是汗流浹背距淫。 一陣腳步聲響...
    開封第一講書人閱讀 32,812評論 1 268
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留婶希,地道東北人榕暇。 一個月前我還...
    沈念sama閱讀 47,693評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像喻杈,于是被迫代替她去往敵國和親彤枢。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,577評論 2 353

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

  • Promise的含義: ??Promise是異步編程的一種解決方案筒饰,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和...
    呼呼哥閱讀 2,170評論 0 16
  • 前言 在Promise之前缴啡,js的異步編程都是采用回調(diào)函數(shù)和事件的方式。但是這種編程方式在處理復(fù)雜業(yè)務(wù)的情況下瓷们,很...
    卓三陽閱讀 831評論 0 1
  • 如果瀏覽已經(jīng)有了Promise對象业栅,那么頁就說明瀏覽器的js引擎里已經(jīng)有了Promsise隊列,這樣就可以利用Pr...
    羊烊羴閱讀 505評論 0 0
  • ES6-Promise對象 (上) 1.Promise對象方法 (1)Promise.all(iterable);...
    卓三陽閱讀 338評論 0 1
  • Promiese 簡單說就是一個容器谬晕,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果碘裕,語法上說,Pr...
    雨飛飛雨閱讀 3,357評論 0 19