摘要:反之,操作失敗,對象由狀態轉換為狀態,此時回調函數會執行方法。這里需要注意的是,雖然在之后便執行了方法,但是并不是意味著往后的對象不執行了,其他的還是對象還是要執行的,只是不會再調用函數。
在 掘金上看見一篇寫promise的文章,感覺作者寫的很棒,文章鏈接在這:八段代碼徹底掌握 Promise 。看完之后感覺學到了很多,所以又重新把JavaScript Promise迷你書(中文版)刷了一遍,以下是我對于promise的理解。
Promise 是什么?所謂Promise,簡單說就是一個容器,里面保存著某個未來才會結束的事件(通常是一個異步操作)的結果。從語法上說,Promise 是一個對象,從它可以獲取異步操作的消息。Promise 提供統一的 API,各種異步操作都可以用同樣的方法進行處理。 —— ECMAScript 6 入門 阮一峰
Promise對象代表一個異步操作,有三種狀態:Pending(準備狀態),Fulfilled(成功狀態,也稱為Resolved狀態),Rejected(失敗狀態)。只有異步操作的結果可以決定promise對象的狀態,操作成功后,promise對象由Pending狀態轉換為Fulfilled狀態,此時回調函數會執行 onFulfilled方法。反之,操作失敗,promise對象由pending狀態轉換為Rejected狀態,此時回調函數會執行onRejected方法。
如下圖所示:
var p1 = new Promise(function(resolve,reject){ resolve("resolve"); }); var p2 = new Promise(function(resolve,reject){ reject("reject"); });
p1 返回一個resolved狀態,值為resolve的Promise對象
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: "resolve"}
p2 返回一個rejected狀態,值為reject的Promise對象
Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: "reject"}Promise 的基本API
Promise.then(onFulfilled,onRejected)
then方法定義了promise狀態變為resolved或者rejected狀態之后的回調函數:
pending->resolved:執行onFulfilled函數,并且將promise對象的值傳給onFulfilled函數
pending->rejected:執行onRejected函數,并且將promise對象的值傳給onRejected函數
代碼示例如下:
var p = new Promise(function(resolve, reject){ console.log("create a promise"); resolve("success"); }); console.log("after new Promise"); p.then(function onFulfilled(value){ console.log(value); },function onRejected(error){ console.log(error); });
運行結果如下:
"create a promise" "after new Promise" "success"
new Promise返回一個resolved狀態的promise對象,所以在p.then()方法中調用的是onFulfilled函數。
創建promise時,promise對象中的函數是立即執行的,并不是在調用then方法的時候才會去執行,所以首先會輸出"create a promise"。但是執行的代碼是異步代碼,所以"after new Promise"會在"success"之前輸出。
promise.catch(onRejected);
catch方法捕獲了promise運行過程中的異常。catch與then方法中的onRejected的不同是,onRejected 函數只能在promise狀態變為rejected的時候調用,但catch既可以在promise狀態變為rejected的時候調用,又可以捕獲第一個onFulfilled方法中出現的錯誤。
可以參考promise迷你書中的這一段代碼:
function throwError(value) { // 拋出異常 throw new Error(value); } // <1> onRejected不會被調用 function badMain(onRejected) { return Promise.resolve(42).then(throwError, onRejected); } // <2> 有異常發生時onRejected會被調用 function goodMain(onRejected) { return Promise.resolve(42).then(throwError).catch(onRejected); } // 運行示例 badMain(function(){ console.log("BAD"); }); goodMain(function(){ console.log("GOOD"); });
在這段代碼中,badMain函數中傳入onRejected參數,因為Promise.resolve(42)返回一個resolved狀態的promise對象(這個api的用法會在下一節中說到),所以會去調用throwError函數,throwError函數中拋出的異常onRejected是捕獲不到的,但是catch可以捕獲到。
這個方法會根據傳進來的參數的不同,返回不同的promise對象。
//1.傳入的參數是一個普通值 var p1 = Promise.resolve(1);//返回一個將該對象作為值的新promise對象 //2.傳入的參數是一個Promise對象 var p2 = Promise.resolve(p1);//返回接收到的promise對象 p1 === p2 //true
在迷你書中介紹了三種情況,除了上面兩種之外,還有一種thenable類型的對象的時候,那種這里就不做介紹了,有興趣的朋友可以自己去看看啊~
這個方法跟Promise.resolve方法一樣,會根據傳進來的參數的不同,返回不同的promise對象。
//1.傳入的參數是一個普通值 var p3 = Promise.reject(1);//返回一個將該對象作為值的新promise對象 //2.傳入的參數是一個Promise對象 var p4 = Promise.reject(p3);//返回一個新的promise對象 p3 === p4 //false
跟resolve不同的是,當傳入的參數是一個Promise對象的時候,會返回一個rejected狀態的新promise對象。
Promise.all接收一個 promise對象的數組作為參數,當這個數組里的所有promise對象全部變為resolve或reject狀態的時候,它才會去調用?.then?方法。
示例代碼:
var p1 = Promise.resolve(1), p2 = Promise.resolve(2), p3 = Promise.resolve(3); Promise.all([p1, p2, p3]).then(function (results) { console.log(results); // [1, 2, 3] });
Promise.race也是接收一個 promise對象的數組作為參數,參數 promise 數組中的任何一個promise對象如果變為resolve或者reject的話, 該函數就會返回,并使用這個promise對象的值進行resolve或者reject。
var p1 = Promise.resolve(1), p2 = Promise.resolve(2), p3 = Promise.resolve(3); Promise.race([p1, p2, p3]).then(function (value) { console.log(value); // 1 });
這里需要注意的是,雖然在p1resolved之后便執行了then方法,但是并不是意味著往后的promise對象不執行了,其他的還是promise對象還是要執行的,只是不會再調用then函數。
下面這個demo便可以看出:
var p1 = new Promise(function(resolve,reject){ console.log("I am p1!"); resolve(1); }); var p2 = new Promise(function(resolve,reject){ console.log("I am p2!"); resolve(2); }); var p3 = new Promise(function(resolve,reject){ console.log("I am p3!"); resolve(3); }); Promise.race([p1, p2, p3]).then(function (value) { console.log(value); });
運行結果:
I am p1! I am p2! I am p3! 1Promise Demo
這是個很大的demo,,^-^, 涵蓋了很多小知識點,
var p_1 = new Promise(function(resolve,reject){ resolve(1); }); var p_2 = Promise.resolve(1); var p_3 = Promise.reject(1); var p_4 = Promise.resolve(p_2); // 方式1 var p1 = new Promise(function(resolve, reject){ resolve(Promise.resolve("resolve")); }); var p2 = new Promise(function(resolve, reject){ resolve(Promise.reject("reject")); }); var p3 = new Promise(function(resolve, reject){ reject(Promise.resolve("resolve")); }); var p4 = new Promise(function(resolve, reject){ reject(Promise.reject("reject")); }); //方式2 var p1 = Promise.resolve(Promise.resolve("resolve")) var p2 = Promise.resolve(Promise.reject("reject")) var p3 = Promise.reject(Promise.resolve("resolve")) var p4 = Promise.reject(Promise.reject("reject")) //定義回調函數 p1.then( function fulfilled(value){ console.log("fulfilled1: " + value); }, function rejected(err){ console.log("rejected1: " + err); } ); p2.then( function fulfilled(value){ console.log("fulfilled2: " + value); }, function rejected(err){ console.log("rejected2: " + err); } ); p3.then( function fulfilled(value){ console.log("fulfilled3: " + value); }, function rejected(err){ console.log("rejected3: " + err); } ); p4.then( function fulfilled(value){ console.log("fulfilled4: " + value); }, function rejected(err){ console.log("rejected4: " + err); } );
采用new Promise 方式創建對象和采用Promise.resolve方法創建出來的對象其實是一樣的,可以把Promise.resolve看做new Promise 的語法糖。只不過需要注意的是,在上面介紹resolve方法的時候說過,如果傳入的參數是一個promise對象,會直接返回這個對象,,所以p_2===p_4輸出的是true,但是通過new的方式創建出來的對象都是新創建的,所以new出來的對象跟別的對象都不會全等,即p_1===p_2會輸出false。
兩種方式定義的p1,p2,p3,p4都是相同的,從這段代碼可以看出,不論是用那種方式創建promise對象,如果使用Promise.resolve方法傳入一個新對象,還是會去‘讀取’(可理解為)這個對象的,但是Promise.reject方法傳入一個新對象,并不會去‘讀取’這個對象,而會直接返回這個這個對象。(這個‘讀取’的概念并不是promise中的概念,只是我的個人理解,在八段代碼徹底掌握 Promise 這篇文章中,作者把他解釋為‘拆箱’,也是作者的一種讓人理解起來更簡單的思路,至于promise官方文檔中的規定,目前還沒有去仔細深入研究,有時間會去看一下^-^)
從這段代碼可以看出,兩種方式的執行順序會有差別,至于為什么,今天也查找了很多資料,但是并沒有找到原因,有研究過的大神歡迎指導~~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/84612.html
摘要:則是把類似的異步處理對象和處理規則進行規范化,并按照采用統一的接口來編寫,而采取規定方法之外的寫法都會出錯。這個對象有一個方法,指定回調函數,用于在異步操作執行完后執行回調函數處理。到目前為止,已經學習了創建對象和用,方法來注冊回調函數。 Promise 本文從js的異步處理出發,引入Promise的概念,并且介紹Promise對象以及其API方法。 js里的異步處理 可以參考這篇文章...
摘要:就算改變已經發生了,你再對對象添加回調函數,也會立即得到這個結果。有了對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調函數。但是在這里,會得到這樣的結果關于是用于指定發生錯誤時的回調函數。 看了很多關于promise的文章,此篇文章做以總結。由于Javascript是一種單線程的語言,所有的代碼必須按照所謂的自上而下的順序來執行。本特性帶來的問題就是,一些將來的、未...
摘要:關于的個提示正如同事所說的那樣,在工作中表現優異。這篇文章會給你一些如何改善與之間關系的建議。但是對于一個初學者來說,可能就不會了。在中不論你使用或者都會創建一個新的。這個是剛剛鏈式調用的和剛剛加上的的組合。 關于 Promise 的 9 個提示 正如同事所說的那樣,Promise 在工作中表現優異。 showImg(https://segmentfault.com/img/remot...
摘要:秒鐘后調用函數觀察上述代碼執行,在的控制臺輸出可以看到就是典型的異步操作統一執行邏輯,不關心如何處理結果,然后,根據結果是成功還是失敗,在將來的某個時候調用函數或函數。 Promise的學習和拓展 以前開發的時候偶爾會在請求中,或者其他場景中用到promise,只知道它是什么(鏈式調用,用于請求的后返回值得操作之類的),大概怎么用,卻沒有深入了解。 起因:(在參考了廖雪峰的prom...
摘要:執行,輸出,宏任務執行結束。到此為止,第一輪事件循環結束。參考入門阮一峰系列之我們來聊聊一道關于應用的面試題阿里前端測試題關于中函數的理解與應用這一次,徹底弄懂執行機制一個面試題原生的所有方法介紹附一道應用場景題目異步流程控制 說明 最近在復習 Promise 的知識,所以就做了一些題,這里挑出幾道題,大家一起看看吧。 題目一 const promise = new Promise((...
閱讀 5265·2021-09-22 15:59
閱讀 1856·2021-08-23 09:42
閱讀 2561·2019-08-29 18:42
閱讀 3444·2019-08-29 10:55
閱讀 2058·2019-08-27 10:57
閱讀 1759·2019-08-26 18:27
閱讀 2722·2019-08-23 18:26
閱讀 2912·2019-08-23 14:40