ES6-promise


Promise 是異步編程的一種解決方案缚去,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大辜荠。它由社區(qū)最早提出和實現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn)政冻,統(tǒng)一了用法枚抵,原生提供了Promise對象。所謂Promise明场,簡單說就是一個容器汽摹,里面保存著某個未來才會結(jié)束的事件(通常是一個異步操作)的結(jié)果。從語法上說苦锨,Promise 是一個對象逼泣,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API舟舒,各種異步操作都可以用同樣的方法進(jìn)行處理拉庶。Promise對象有以下兩個特點:
1. 對象的狀態(tài)不受外界影響。Promise對象代表一個異步操作秃励,有三種狀態(tài):pending(進(jìn)行中)氏仗、fulfilled(已成功)和rejected(已失敗)夺鲜。只有異步操作的結(jié)果皆尔,可以決定當(dāng)前是哪一種狀態(tài),任何其他操作都無法改變這個狀態(tài)币励。這也是Promise這個名字的由來慷蠕,它的英語意思就是“承諾”,表示其他手段無法改變食呻。
2. 一旦狀態(tài)改變流炕,就不會再變澎现,任何時候都可以得到這個結(jié)果。Promise對象的狀態(tài)改變每辟,只有兩種可能:從pending變?yōu)閒ulfilled和從pending變?yōu)閞ejected昔头。只要這兩種情況發(fā)生,狀態(tài)就凝固了影兽,不會再變了,會一直保持這個結(jié)果莱革,這時就稱為 resolved(已定型)峻堰。如果改變已經(jīng)發(fā)生了,你再對Promise對象添加回調(diào)函數(shù)盅视,也會立即得到這個結(jié)果捐名。這與事件(Event)完全不同,事件的特點是闹击,如果你錯過了它镶蹋,再去監(jiān)聽,是得不到結(jié)果的赏半。
--來自官方文檔

Javascript是一種單線程的語言贺归,所有的代碼必須按照所謂的“自上而下”的順序來執(zhí)行。本特性帶來的問題就是断箫,一些將來的拂酣、未知的操作,必須異步實現(xiàn)仲义。之前我們想要執(zhí)行一些比較復(fù)雜的異步操作婶熬,就會嵌套很多層回調(diào)函數(shù),引入ES6中Promise這個概念埃撵,處理起來就比較簡單了赵颅。

//原始方法
async1(function(){
    console.log('async1執(zhí)行完畢');
    async2(function(){
        console.log('async2執(zhí)行完畢');
        async3(function(
            console.log('async3執(zhí)行完畢');
            async4(funciton(){
                console.log('async4執(zhí)行完畢');
                async5(function(){
                    console.log('async5執(zhí)行完畢');
                    console.log('流程執(zhí)行完畢');  
                });
            });
        )); 
    });
});

是不是看迷糊了,在真正的項目開發(fā)中也許會遇到更加復(fù)雜的執(zhí)行情況暂刘。

//ES6-Promise
Promise.then(() => {
    console.log('async1執(zhí)行完畢');
}).then(() => {
    console.log('async2執(zhí)行完畢');
}).then(() => {
    console.log('async3執(zhí)行完畢');
}).then(() => {
    console.log('async4執(zhí)行完畢');
}).then(() => {
    console.log('async5執(zhí)行完畢');
    console.log('流程執(zhí)行完畢');
});

這樣看是不是清晰多了饺谬。
ES6-Promise中有以下幾個操作方法,鏈?zhǔn)讲僮鳌?code>resolve鸳惯、reject商蕴、catchall芝发、race绪商。

一、鏈?zhǔn)讲僮?/h6>

從表面上看辅鲸,Promise只是能夠簡化層層回調(diào)的寫法格郁,而實質(zhì)上,Promise的精髓是“狀態(tài)”,用維護(hù)狀態(tài)例书、傳遞狀態(tài)的方式來使得回調(diào)函數(shù)能夠及時調(diào)用锣尉,它比傳遞callback函數(shù)要簡單、靈活的多决采。

let runAsync1 = () => {
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('異步任務(wù)1執(zhí)行完成');
            resolve('數(shù)據(jù)1');
        }, 1000);
    });
    return p;            
}
let runAsync2 = () =>{
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('異步任務(wù)2執(zhí)行完成');
            resolve('數(shù)據(jù)2');
        }, 2000);
    });
    return p;            
}
let runAsync3 = () =>{
    let p = new Promise((resolve, reject) => {
        setTimeout(() => {
            console.log('異步任務(wù)3執(zhí)行完成');
            resolve('數(shù)據(jù)3');
        }, 2000);
    });
    return p;            
}
runAsync1().then((data) => {
    console.log(data);
    return runAsync2();
}).then((data) => {
    console.log(data);
    return runAsync3();
}).then((data) => {
    console.log(data);
});

這樣能夠按順序自沧,每隔兩秒輸出每個異步回調(diào)中的內(nèi)容,在runAsync2中傳給resolve的數(shù)據(jù)树瞭,能在接下來的then方法中拿到拇厢。以上代碼的執(zhí)行結(jié)果為:

而我們更改調(diào)用順序,并在最后一步晒喷,返回‘執(zhí)行結(jié)束’字符串孝偎。

runAsync1().then((data) => {
    console.log(data);
    return runAsync3();
}).then((data) => {
    console.log(data);
    return runAsync2();
}).then((data) => {
    console.log(data);
    return '執(zhí)行結(jié)束';
}).then((data) => {
    console.log(data);
});

執(zhí)行結(jié)果如下:

這樣我們就可以很方便、清晰的去決定我們的程序的執(zhí)行順序凉敲,達(dá)到預(yù)計想要的結(jié)果衣盾。

二、resolve 操作

resolve的作用就是把Promise的狀態(tài)置為resolved爷抓,這樣我們在then中就能捕捉到势决,然后執(zhí)行“成功”情況的回調(diào)。這里就不做細(xì)展示了废赞,在之前的例子中都可以看到詳細(xì)的代碼結(jié)構(gòu)徽龟。

三、reject 操作

reject和resolve類似唉地,reject的作用就是把Promise的狀態(tài)置為rejected据悔,這樣我們在then中就能捕捉到,然后執(zhí)行“失敗”情況的回調(diào)耘沼。但是resolve是必須的參數(shù)极颓,reject不是必須的。

let compare = (num1,num2) => {
    var p = new Promise((resolve, reject) => {
        if (num1 < num2) {
            resolve('resolved:'+num1+'<'+num2);
        } else if (num1 === num2) {
            resolve('resolved:'+num1+'='+num2);
        } else {
            reject('rejected:'+num1+'>'+num2);
        }
    });
    return p;            
}

compare(7,10).then((data) => {
    console.log(data);
},(err) => {
    console.log(err);
});

compare(10,10).then((data) => {
    console.log(data);
},(err) => {
    console.log(err);
});

compare(10,7).then((data) => {
    console.log(data);
},(err) => {
    console.log(err);
});

如以上程序如果第一個參數(shù)小于等于第二個參數(shù)群嗤,則Promise的狀態(tài)為成功菠隆;如果第一個參數(shù)大于第二個參數(shù),則Promise的狀態(tài)為失敗狂秘。如圖:
四骇径、catch 操作

catch的一個作用與reject類似。如:

compare(10,7).then((data) => {
    console.log(data);
}).catch((err) => {
    console.log(err);
});

結(jié)果:

在執(zhí)行resolve的回調(diào)時者春,如果拋出異常了(代碼出錯了)破衔,那么就會報錯卡死js。如:

compare(10,7).then((data) => {
    console.log(data);
    console.log(msg);
},(err) => {
    console.log(err);
})

執(zhí)行結(jié)果:

而catch的另一個作用就是在執(zhí)行resolve的回調(diào)時钱烟,如果拋出異常了(代碼出錯了)晰筛,js不會報錯卡死嫡丙,而是會進(jìn)到這個catch方法中。如:

compare(7,10).then((data) => {
    console.log(data);
    console.log(msg);
}).catch((err) => {
    console.log(err);
});

執(zhí)行結(jié)果:
五读第、all 操作

all方法提供了并行執(zhí)行異步操作的能力曙博,并且在所有異步操作執(zhí)行完后才執(zhí)行回調(diào)。all里的所有個異步操作的并行執(zhí)行的怜瞒,等到它們都執(zhí)行完后才會進(jìn)到then里面父泳,在then里面我們會接受到一個數(shù)組就是all的異步操作依次得到的值。如:

Promise.all([
    runAsync1(), runAsync2(), runAsync3()
]).then(function(data){
    console.log(data);
});

執(zhí)行結(jié)果:
六吴汪、race 操作

all方法的執(zhí)行原理是所有異步操作都執(zhí)行完才會進(jìn)入then操作尘吗,也就是要等最慢的一個執(zhí)行完才會進(jìn)入then操作;而race方法的執(zhí)行原理則是最快的一個異步操作執(zhí)行完就立即進(jìn)入then操作浇坐,其他異步操作會繼續(xù)進(jìn)行但不會進(jìn)入then操作。如下:

Promise.race([
    runAsync1(), runAsync2(), runAsync3()
]).then(function(results){
    console.log(results);
});

執(zhí)行結(jié)果:

只有不斷找尋機(jī)會的人才會及時把握機(jī)會黔宛。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末近刘,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子臀晃,更是在濱河造成了極大的恐慌觉渴,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件徽惋,死亡現(xiàn)場離奇詭異案淋,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)险绘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進(jìn)店門踢京,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人宦棺,你說我怎么就攤上這事瓣距。” “怎么了代咸?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵蹈丸,是天一觀的道長。 經(jīng)常有香客問我呐芥,道長逻杖,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任思瘟,我火速辦了婚禮荸百,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘潮太。我一直安慰自己管搪,他們只是感情好虾攻,可當(dāng)我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著更鲁,像睡著了一般霎箍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澡为,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天漂坏,我揣著相機(jī)與錄音,去河邊找鬼媒至。 笑死顶别,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的拒啰。 我是一名探鬼主播驯绎,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼谋旦!你這毒婦竟也來了剩失?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤册着,失蹤者是張志新(化名)和其女友劉穎拴孤,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體甲捏,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡演熟,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了司顿。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芒粹。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖大溜,靈堂內(nèi)的尸體忽然破棺而出是辕,到底是詐尸還是另有隱情,我是刑警寧澤猎提,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布获三,位于F島的核電站,受9級特大地震影響锨苏,放射性物質(zhì)發(fā)生泄漏疙教。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一伞租、第九天 我趴在偏房一處隱蔽的房頂上張望贞谓。 院中可真熱鬧,春花似錦葵诈、人聲如沸裸弦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽理疙。三九已至晕城,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間窖贤,已是汗流浹背砖顷。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留赃梧,地道東北人滤蝠。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像授嘀,于是被迫代替她去往敵國和親物咳。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 43,697評論 2 351

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