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