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