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