JavaScript異步編程Promise模式的6個(gè)特性
在我們開(kāi)始正式介紹之前,我們想看看Javascript Promise的樣子:
var p = new Promise(function(resolve, reject) {
resolve("hello world");
});
p.then(function(str) {
alert(str);
});
1. then()返回一個(gè)Forked Promise
以下兩段代碼有什么區(qū)別呢?
// Exhibit A
var p = new Promise(/*...*/);
p.then(func1);
p.then(func2);
// Exhibit B
var p = new Promise(/*...*/);
p.then(func1)
.then(func2);
如果你認(rèn)真以上兩段代碼等同的話,那么Promises只不過(guò)是一個(gè)一維的回調(diào)函數(shù)數(shù)組。然而,其實(shí)不是這樣的。每一個(gè)then()調(diào)用都返回一個(gè)forked promise。因此,ExhibitA中,如果func1()拋出一個(gè)異常,func2()仍舊正常調(diào)用。
在ExhibitB中,如果func1()拋出一個(gè)錯(cuò)誤,fun2()將不會(huì)被調(diào)用,因?yàn)榈谝粋€(gè)調(diào)用返回了一個(gè)新的promise,這個(gè)在func1()中會(huì)被拒絕。結(jié)果是func2()被跳過(guò)。
總結(jié):promises可以被fork成多個(gè)路徑,類(lèi)似復(fù)雜的流程圖。
2. Callback應(yīng)該傳遞結(jié)果
當(dāng)你運(yùn)行下面代碼的時(shí)候什么會(huì)得到警告提示呢?
var p = new Promise(function(resolve, reject) {
resolve("hello world");
});
p.then(function(str) {})
.then(function(str) {
alert(str);
});
第二個(gè)then()中的alert沒(méi)有顯示任何內(nèi)容。這是因?yàn)榛卣{(diào)函數(shù),在promise的上下文中,因?yàn)榻Y(jié)果的變化并沒(méi)有回調(diào)函數(shù)。promise期望你的回調(diào)函數(shù)返回同樣的結(jié)果或者返回一個(gè)替換結(jié)果,然后被傳遞到下一個(gè)回調(diào)函數(shù)中。
類(lèi)似使用adpater來(lái)變化結(jié)果,如下:
var feetToMetres = function(ft) { return ft*12*0.0254 };
var p = new Promise(/*...*/);
p.then(feetToMetres)
.then(function(metres) {
alert(metres);
});
3. 只有來(lái)自上一層的異??梢员徊蹲?/P>
這兩段代碼有什么區(qū)別?
// Exhibit A
new Promise(function(resolve, reject) {
resolve("hello world");
})
.then(
function(str) {
throw new Error("uh oh");
},
undefined
)
.then(
undefined,
function(error) {
alert(error);
}
);
// Exhibit B
new Promise(function(resolve, reject) {
resolve("hello world");
})
.then(
function(str) {
throw new Error("uh oh");
},
function(error) {
alert(error);
}
);
在第一段代碼中,在第一個(gè)then()中的異常被拋出,將會(huì)被第二個(gè)then()捕捉,然后“uh oh”警告將會(huì)被觸發(fā)。這個(gè)遵循只有前一個(gè)層次的異常會(huì)被捕捉。
在第二段代碼中,回調(diào)函數(shù)和錯(cuò)誤回調(diào)函數(shù)是同一個(gè)層次,意味著當(dāng)異常在回調(diào)中拋出,將不會(huì)被捕捉。事實(shí)上,第二段代碼的錯(cuò)誤回調(diào)將只會(huì)在promise為拒絕狀態(tài)或者promise本身出錯(cuò)的情況下拋出
4. 錯(cuò)誤可以被恢復(fù)
在一個(gè)錯(cuò)誤回調(diào)函數(shù)中,如果你不重新拋出錯(cuò)誤,promise會(huì)假設(shè)你已經(jīng)從錯(cuò)誤中恢復(fù),并且反轉(zhuǎn)成為已解決狀態(tài)。在下一個(gè)例子中,"i'm saved" 將會(huì)被顯示,這是因?yàn)樵诘谝粋€(gè)then()中的錯(cuò)誤回調(diào)沒(méi)有重新拋出異常。
var p = new Promise(function(resolve, reject) {
reject(new Error("pebkac"));
});
p.then(
undefined,
function(error) { }
)
.then(
function(str) {
alert("I am saved!");
},
function(error) {
alert("Bad computer!");
}
);
Promise可以被看作洋蔥上的層次。每一個(gè)then()添加另外一個(gè)層次到洋蔥上。每一個(gè)層次代表了一個(gè)被處理的活動(dòng)。當(dāng)層次結(jié)束,結(jié)果被認(rèn)為已經(jīng)修復(fù)并且為下一個(gè)層次做好了準(zhǔn)備。
5. Promises可以被暫停
因?yàn)槟阋呀?jīng)準(zhǔn)備好了在一個(gè)then()方法中執(zhí)行,并不意味著你不能夠暫停并且提前運(yùn)行其他。 為了暫停目前的promise,或者讓它等待以便另外一個(gè)promise完成,簡(jiǎn)單在then()中返回另外一個(gè)promise。
var p = new Promise(/*...*/);
p.then(function(str) {
if(!loggedIn) {
return new Promise(/*...*/);
}
})
.then(function(str) {
alert("Done.");
})
在前面代碼中,直到新的promise解析后提示才會(huì)出現(xiàn)。這是一個(gè)方便的方式在已存在的異步代碼路徑中來(lái)引入更多地依賴(lài)。例如,你可能發(fā)現(xiàn)用戶session已經(jīng)timeout,并且你可能希望在繼續(xù)前面的代碼路徑前初始化第二個(gè)登陸。
6. Resolved Promises并不會(huì)立刻執(zhí)行
運(yùn)行下面代碼會(huì)得到提示框么?
function runme() {
var i = 0;
new Promise(function(resolve) {
resolve();
})
.then(function() {
i += 2;
});
alert(i);
}
因?yàn)閜romise被立刻解析,然后then()方法被立刻執(zhí)行,所以你可能會(huì)認(rèn)為會(huì)探出提示2。但是promise定義要求所有的調(diào)用都被強(qiáng)制異步。因此提示會(huì)在被修改前生成。
- Javascript異步編程之你真的懂Promise嗎
- JavaScript異步編程之Promise的初步使用詳解
- 深入理解JS異步編程-Promise
- 詳解JavaScript異步編程中jQuery的promise對(duì)象的作用
- javascript使用Promise對(duì)象實(shí)現(xiàn)異步編程
- 異步JavaScript編程中的Promise使用方法
- javascript異步編程代碼書(shū)寫(xiě)規(guī)范Promise學(xué)習(xí)筆記
- Javascript中的異步編程規(guī)范Promises/A詳細(xì)介紹
- Javascript異步編程模型Promise模式詳細(xì)介紹
- JS異步編程Promise對(duì)象詳解
相關(guān)文章
微信小程序自定義單選框樣式實(shí)現(xiàn)單選功能
這篇文章主要為大家詳細(xì)介紹了微信小程序自定義單選框樣式實(shí)現(xiàn)單選功能,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2022-07-07JS從數(shù)組中隨機(jī)取出幾個(gè)數(shù)組元素的方法
JS如何從一個(gè)數(shù)組中隨機(jī)取出一個(gè)元素或者幾個(gè)元素呢?其實(shí)方法很簡(jiǎn)單,下面小編給大家分享了JS隨機(jī)取出幾個(gè)數(shù)組元素的方法,非常不錯(cuò),需要的朋友參考下2016-08-08JS實(shí)現(xiàn)表格數(shù)據(jù)各種搜索功能的方法
這篇文章主要介紹了JS實(shí)現(xiàn)表格數(shù)據(jù)各種搜索功能的方法,可實(shí)現(xiàn)忽略大小寫(xiě),模糊搜索,多關(guān)鍵搜索等功能,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2015-03-03微信小程序?qū)崿F(xiàn)通過(guò)js操作wxml的wxss屬性示例
這篇文章主要介紹了微信小程序?qū)崿F(xiàn)通過(guò)js操作wxml的wxss屬性,結(jié)合實(shí)例形式分析了微信小程序使用js操作wxml的wxss屬性相關(guān)原理、實(shí)現(xiàn)技巧與操作注意事項(xiàng),需要的朋友可以參考下2018-12-12基于JS實(shí)現(xiàn)二維碼圖片固定在右下角某處并跟隨滾動(dòng)條滾動(dòng)
這篇文章主要介紹了基于JS實(shí)現(xiàn)二維碼圖片固定在右下角某處并跟隨滾動(dòng)條滾動(dòng),代碼簡(jiǎn)單易懂非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-02-02npm安裝依賴(lài)時(shí)出現(xiàn)Peer Dependencies沖突報(bào)錯(cuò)解決分析
這篇文章主要為大家介紹了npm安裝依賴(lài)時(shí)出現(xiàn)Peer Dependencies沖突報(bào)錯(cuò)解決分析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09js 判斷瀏覽器類(lèi)型 去全角、半角空格 自動(dòng)關(guān)閉當(dāng)前窗口
去全角、半角空格 自動(dòng)關(guān)閉當(dāng)前窗口等實(shí)現(xiàn)函數(shù)。2009-04-04