摘要:已完成意味著操作成功完成。處理實(shí)例實(shí)例生成以后,可以用方法分別指定狀態(tài)和狀態(tài)的回調(diào)函數(shù)。第二個(gè)回調(diào)函數(shù)在的狀態(tài)變成時(shí)被調(diào)用。方法是的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。具體的使用示例如下情形一全部成功的情況結(jié)果為。
一.關(guān)于Promise
promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案(回調(diào)函數(shù)和事件)更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6將其寫(xiě)進(jìn)了語(yǔ)言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise對(duì)象。
所謂Promise,簡(jiǎn)單說(shuō)就是一個(gè)容器,里面保存著某個(gè)未來(lái)才會(huì)結(jié)束的事件(通常是一個(gè)異步操作)的結(jié)果。從語(yǔ)法上說(shuō),Promise 是一個(gè)對(duì)象,從它可以獲取異步操作的消息。Promise 提供統(tǒng)一的 API,各種異步操作都可以用同樣的方法進(jìn)行處理。
它代表一個(gè)異步操作。有三種狀態(tài):
pending(進(jìn)行中): 初始狀態(tài), 初始狀態(tài),未完成或拒絕。
resolved(已完成): 意味著操作成功完成。又名fulfilled。
rejected(已失敗): 意味著操作失敗。
有了Promise,就可以將異步操作以同步操作的流程表達(dá)出,但它也有如下缺點(diǎn):
一旦創(chuàng)建它就會(huì)立即執(zhí)行,無(wú)法中途取消。
如果不設(shè)置回調(diào)函數(shù),Promise內(nèi)部拋出的錯(cuò)誤,不會(huì)反應(yīng)到外部。
當(dāng)處于Pending狀態(tài)時(shí),無(wú)法得知目前進(jìn)展到哪一個(gè)階段(剛剛開(kāi)始還是即將完成)。
二.應(yīng)用示例 1. 創(chuàng)建Promisevar promise = new Promise( /* executor */ function(resolve, reject){ ... } );
? executor函數(shù)由Promise實(shí)現(xiàn)立即執(zhí)行,傳遞resolve和reject函數(shù). (在Promise構(gòu)造函數(shù)之前調(diào)用執(zhí)行器甚至返回創(chuàng)建的對(duì)象)
? 在?executor?內(nèi)部,promise有如下的狀態(tài)變化可能:
? 1. resolve被調(diào)用,promise由pending變?yōu)閞esolved,代表該P(yáng)romise被成功解析(resolve)
? 2.reject?被調(diào)用,promise由pending變?yōu)閞ejected,代表該P(yáng)romise的值不能用于后續(xù)處理,即被拒絕了
2.處理Promise實(shí)例注意:
如果在executor?方法的執(zhí)行過(guò)程中拋出了任何異常,那么promise立即被拒絕(即相當(dāng)于reject方法被調(diào)用),executor?的返回值也就會(huì)被忽略。
如果一個(gè)promise對(duì)象處在resolved或rejected狀態(tài)而不是pending狀態(tài),那么它也可以被稱為settled狀態(tài)。
then:Promise實(shí)例生成以后,可以用then方法分別指定Resolved狀態(tài)和Reject狀態(tài)的回調(diào)函數(shù)。
promise.then(function(value) { // success 狀態(tài)為Resolved時(shí)調(diào)用 }, function(error) { // failure 狀態(tài)為Reject時(shí)調(diào)用 });
then方法可以接受兩個(gè)回調(diào)函數(shù)作為參數(shù)。
第一個(gè)回調(diào)函數(shù):在promise的狀態(tài)變成resolved時(shí)被調(diào)用。它的參數(shù)promise的resolve方法的返回值。
第二個(gè)回調(diào)函數(shù):在promise的狀態(tài)變成rejected時(shí)被調(diào)用。它的參數(shù)promise的reject方法的返回值。且為可選參數(shù)。
catch:Promise.prototype.catch方法是.then(null, rejection)的別名,用于指定發(fā)生錯(cuò)誤時(shí)的回調(diào)函數(shù)。
promise.then(function(posts) { // ... }).catch(function(error) { console.log("發(fā)生錯(cuò)誤!", error); // 處理 promise 和 前一個(gè)回調(diào)函數(shù)運(yùn)行時(shí)發(fā)生的錯(cuò)誤 });
擴(kuò)展:
Promise.prototype.then和?Promise.prototype.catch方法返回?promises對(duì)象, 所以它們可以被鏈?zhǔn)秸{(diào)用。但此時(shí)返回的是以函數(shù)返回值生成的新的Promise實(shí)例,不是原來(lái)那個(gè)Promise實(shí)例。
3.將多個(gè)Promise實(shí)例,包裝成一個(gè)新的Promise實(shí)例注意問(wèn)題:
Promise 對(duì)象的錯(cuò)誤具有“冒泡”性質(zhì),會(huì)一直向后傳遞,直到被捕獲為止。也就是說(shuō),錯(cuò)誤總是會(huì)被下一個(gè)catch語(yǔ)句捕獲。
Promise.all(iterable)?:當(dāng)所有在可迭代參數(shù)中的?promises 已完成,或者第一個(gè)傳遞的?promise(指 reject)失敗時(shí),返回?promise。
var p = Promise.all([p1, p2, p3]);
當(dāng)p1、p2和p3的狀態(tài)均為resolved時(shí)p的狀態(tài)為resolved。
當(dāng)p1、p2或p3中的任意一個(gè)被rejected,p的狀態(tài)就變成rejected,此時(shí)第一個(gè)被reject的實(shí)例的返回值,會(huì)傳遞給p的回調(diào)函數(shù)。
具體的使用示例如下:
情形一:全部成功的情況
Promise.all([Promise.resolve("foo"),Promise.resolve("bar"),Promise.resolve("test")]) .then(function(result){ console.log(result); //結(jié)果為:[foo,bar,test]。即所有返回值的數(shù)組。 }) .catch(function(error) { console.log("error"); //不會(huì)被執(zhí)行 });
情形二:全部失敗或部分失敗
Promise.all([Promise.resolve("foo"),Promise.reject("barError"),Promise.reject("testError")]) .then(function(result){ console.log(result); //成功回調(diào) 不會(huì)被執(zhí)行 }) .catch(function(error) { console.log(error); //結(jié)果為barError或testError。即第一個(gè)被reject的值。 });三.常見(jiàn)的使用誤區(qū)
忘記添加 .catch()
通常情況,promise有如下兩種處理方式:
// ------------ 不好的寫(xiě)法 ------------- promise.then(function(data) { // success }, function(err) { //僅處理promise運(yùn)行時(shí)發(fā)生的錯(cuò)誤。無(wú)法處理回調(diào)中的錯(cuò)誤 // error }); // ------------ 好的寫(xiě)法 ------------ promise.then(function(data) { // success }).catch(function(err) { // 處理 promise 和 前一個(gè)回調(diào)函數(shù)運(yùn)行時(shí)發(fā)生的錯(cuò)誤 // error });
因?yàn)閜romise拋出的錯(cuò)誤不會(huì)傳遞到外層代碼。當(dāng)使用沒(méi)有catch的第一種種寫(xiě)法時(shí),成功回調(diào)的錯(cuò)誤將無(wú)法被處理。因此比較好的方式是,總是使用catch方法。
在then或者catch函數(shù)中不使用return
下面是在是用Promise時(shí),一個(gè)很常見(jiàn)的錯(cuò)誤寫(xiě)法:
//------------ 不好的寫(xiě)法 ------------------ promise.then(function?()?{ ??getUserInfo(userId); }).then(function?()?{ // 在這里可能希望在這個(gè)回調(diào)中使用用戶信息,但你可能會(huì)發(fā)現(xiàn)它根本不存在 });
會(huì)發(fā)生上面的錯(cuò)誤,是因?yàn)閷?duì)Promise的返回及鏈?zhǔn)秸{(diào)用的理解不夠。
每一個(gè)promise都會(huì)給你一個(gè)then()方法(或者catch,它們只是then(null,…)的語(yǔ)法糖)。這里我們是在then()方法的內(nèi)部來(lái)看:
promise.then(function?()?{ ??return getUserInfo(userId); }).then(function?(userInfo)?{ HadleUser(userInfo); }).catch(function(error) { console.log(error); });
在回調(diào)中在有三種事可以做:
返回另一個(gè)promise
如果getUserInfo返回一個(gè)Promise,則HadleUser將在該promise變?yōu)閞esolved后執(zhí)行,并以該promise的返回作為入?yún)ⅰ?/p>
返回一個(gè)同步值(或者undefined)
getUserInfo返回一個(gè)同步值,則改值會(huì)被包裝成一個(gè)resolved狀態(tài)的promise,HadleUser將被立刻執(zhí)行,并以getUserInfo返回作為入?yún)ⅰ?/p>
拋出一個(gè)同步錯(cuò)誤。
getUserInfo返回一個(gè)同步錯(cuò)誤,則該錯(cuò)誤會(huì)被包裝成一個(gè)rejected狀態(tài)的promise,最終在catch中被捕獲。此時(shí)HadleUser將不會(huì)被執(zhí)行。
promises丟失
你認(rèn)為下面的代碼會(huì)打印出什么?
Promise.resolve("foo").then(Promise.resolve("bar")).then(function?(result)?{ ??console.log(result); });
如果你認(rèn)為打印出bar,那你就大錯(cuò)特錯(cuò)了。它實(shí)際上會(huì)打印出foo。
原因是當(dāng)你給then()傳遞一個(gè)非函數(shù)(比如一個(gè)promise)值的時(shí)候,它實(shí)際上會(huì)解釋為then(null),這會(huì)導(dǎo)致之前的promise的結(jié)果丟失。
四.最佳實(shí)踐總結(jié)then方法中 永遠(yuǎn)?return?或?throw
如果?promise?鏈中可能出現(xiàn)錯(cuò)誤,一定添加?catch
永遠(yuǎn)傳遞函數(shù)給?then?方法
不要把?promise?寫(xiě)成嵌套
參考鏈接:
Promise -JavaScript | MDN
Promises 很酷,但很多人并沒(méi)有理解就在用了
Promise 對(duì)象
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/82265.html
摘要:使用依賴請(qǐng)預(yù)先創(chuàng)建好和子網(wǎng)如果是需要綁定,請(qǐng)預(yù)先給操作賬號(hào)賦予網(wǎng)絡(luò)相關(guān)權(quán)限需要使用到鏡像倉(cāng)庫(kù),需要?jiǎng)?chuàng)建并將鏡像上傳。實(shí)時(shí)文檔歡迎訪問(wèn)使用須知使用須知使用Cube服務(wù),必須通過(guò)UCloud實(shí)名認(rèn)證服務(wù);使用Cube暴露公網(wǎng)服務(wù),請(qǐng)與UCloud備案團(tuán)隊(duì)聯(lián)系進(jìn)行備案,否則可能會(huì)影響您的服務(wù)正常使用;您的業(yè)務(wù)程序已經(jīng)完成容器化,已有Docker鏡像;您創(chuàng)建的Cube實(shí)例,將默認(rèn)鏡像拉取策略為總是(...
摘要:由服務(wù)端生成在請(qǐng)求任何接口之前,都必須先請(qǐng)求一個(gè)獲取服務(wù)器生成的的接口,獲取之后,才請(qǐng)求其他接口是請(qǐng)求時(shí)間型號(hào)設(shè)備號(hào)系統(tǒng)類(lèi)型加密加密頭部存儲(chǔ)基本參數(shù)加密校驗(yàn)參數(shù)必須填必須填以下為選填,可有可無(wú),任由開(kāi)發(fā)者自己定義類(lèi)型設(shè)備號(hào)版本型號(hào) 傳統(tǒng)API與RESTful API 傳統(tǒng)API 獲取用戶信息 get /api/user/read 更新用戶信息 post /api/user/u...
摘要:對(duì)于集成測(cè)試,直接模擬實(shí)際的環(huán)境,再加上合適的,目前看來(lái)也還不錯(cuò)。這里給出兩個(gè)例子集成測(cè)試單元測(cè)試都是基于寫(xiě)的,各位可以體驗(yàn)其酸爽度。好啦,本期內(nèi)容就此結(jié)束,請(qǐng)保持關(guān)注,期待下期繼續(xù)本系列其他文章入坑須知入坑須知 隨著Vert.x進(jìn)化到3.5.0,本系列也迎來(lái)了新篇章。 CORS的新變化 對(duì)于CORS,搞Web開(kāi)發(fā)(不論你是前端,還是后端)的同志應(yīng)該不陌生,尤其是如今微服務(wù)盛行的時(shí)代,...
摘要:主要是避免引入太多的復(fù)雜性,并且出于靈活部署的需要。以應(yīng)用為例,由于實(shí)際上是在上執(zhí)行,若它被阻塞,即導(dǎo)致后續(xù)請(qǐng)求全部無(wú)法得到處理。因此,最合適的做法就是對(duì)于簡(jiǎn)單業(yè)務(wù),采用異步庫(kù)。本系列其他文章入坑須知入坑須知入坑須知 最開(kāi)始覺(jué)得這個(gè)系列也就最多3篇了不起了(因?yàn)槭虏贿^(guò)三嘛),沒(méi)曾想居然迎來(lái)了第四篇! Kotlin 由于最近決定投身到區(qū)塊鏈的學(xué)習(xí)當(dāng)中的緣故,出于更好的理解它的基本概念,自...
閱讀 3239·2021-10-13 09:40
閱讀 3716·2019-08-30 15:54
閱讀 1318·2019-08-30 13:20
閱讀 3000·2019-08-30 11:26
閱讀 485·2019-08-29 11:33
閱讀 1108·2019-08-26 14:00
閱讀 2370·2019-08-26 13:58
閱讀 3379·2019-08-26 10:39