摘要:是一種異步編程的解決方案相比傳統(tǒng)回調(diào)函數(shù)更合理立即執(zhí)行性立即執(zhí)行返回成功后執(zhí)行控制臺輸出立即執(zhí)行后執(zhí)行返回成功對象表示未來發(fā)生的事件在創(chuàng)建時作為參數(shù)傳入的函數(shù)是會被立即執(zhí)行的只是其中執(zhí)行的代碼可以是異步代碼有些人會認為當對象調(diào)用方法時接受的
Promise是一種異步編程的解決方案,相比傳統(tǒng)回調(diào)函數(shù)更合理.
1.Promise立即執(zhí)行性
let p = new Promise((resolve, reject) => { console.log("立即執(zhí)行!"); resolve("返回成功!") }); console.log("promise后執(zhí)行!"); p.then(value => { console.log(value) });
控制臺輸出:
"立即執(zhí)行!" "promise后執(zhí)行!" "返回成功!"
Promise對象表示未來發(fā)生的事件,在創(chuàng)建promise時,作為promise參數(shù)傳入的函數(shù)是會被立即執(zhí)行的,只是其中執(zhí)行的代碼可以是異步代碼.有些人會認為,當promise對象調(diào)用then方法時,promise接受的函數(shù)才會執(zhí)行,這是錯誤的.所以,代碼中立即執(zhí)行!先于promise后執(zhí)行!輸出.
2.Promise的三種狀態(tài).
let p1 = new Promise((reslove, reject) => { reslove(1); }); let p2 = new Promise((reslove, reject) => { setTimeout(() => { reslove(2); }, 500); }); let p3 = new Promise((reslove, reject) => { setTimeout(() => { reject(3); }, 500); }); console.log(p1); console.log(p2); console.log(p3); setTimeout(() => { console.log(p2); }, 1000); setTimeout(() => { console.log(p3); }, 1000); p1.then(value => { console.log(value); }); p2.then(value => { console.log(value); }); p3.catch(err => { console.log(err); });
控制臺輸出:
Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 1} Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined} 1 2 3 Promise {[[PromiseStatus]]: "resolved", [[PromiseValue]]: 2} Promise {[[PromiseStatus]]: "rejected", [[PromiseValue]]: 3}
Promise內(nèi)部實現(xiàn)是一個狀態(tài)機.Promise有三種狀態(tài): pending,resolved,rejected.當Promise剛創(chuàng)建完成時,處于pending狀態(tài);當Promise中的函數(shù)參數(shù)執(zhí)行了resolve后,Promise由pending狀態(tài)變成resloved狀態(tài);如果Promise的函數(shù)參數(shù)中執(zhí)行的是reject方法,那么Promise會有pending狀態(tài)變成rejected狀態(tài).
3.Promise狀態(tài)不可逆性.
let p1 = new Promise((reslove, reject) => { reslove("成功1!"); reslove("成功2!"); }); let p2 = new Promise((reslove, reject) => { reslove("成功!"); reject("失敗!"); }); p1.then(value => { console.log(value); }); p2.then(value => { console.log(value); });
控制臺輸出:
"成功1!" "成功!"
Promise的狀態(tài)一旦變成resolved或rejected時,Promise的狀態(tài)和值就固定下來了,無論后續(xù)再怎么調(diào)用reslove或是reject方法,都不能改變它的狀態(tài)和值.所以,p1中reslove("成功2!")并不能將p1的值更改為成功2!,p2中reject("失敗!")也不能將p2的狀態(tài)由resolved改變?yōu)閞ejected.
4.鏈式調(diào)用.
let p = new Promise((resolve, reject) => { resolve(1); }); p.then(value => { console.log(value); return value * 2; }).then(value => { console.log(value); }).then(value => { console.log(value); return Promise.resolve("resolve"); }).then(value => { console.log(value); return Promise.reject("reject"); }).then(value => { console.log(`resolve: ${value}`); }, err => { console.log(`reject: ${err}`); })
控制臺輸出:
1 2 undefined "resolve" "reject: reject"
Promise對象的then方法返回一個新的Promise對象,所以可以通過鏈式調(diào)用then方法.then方法接受兩個函數(shù)作為參數(shù),第一個參數(shù)是Promise執(zhí)行成功時的回調(diào),第二個參數(shù)是Promise執(zhí)行失敗時的回調(diào).兩個函數(shù)只會有一個被調(diào)用,函數(shù)返回值將用作創(chuàng)建then返回的Promise對象.這兩個參數(shù)的返回值可以是下面三種情況的一種:
①:return一個同步的值,或者undefined(當沒有返回一個有效值時,默認返回undefined),then方法將返回一個resloved狀態(tài)的Promise對象,Promise對象的值就是這個返回值. ②:return另一個Promise,then方法將根據(jù)這個Promise的狀態(tài)和值創(chuàng)建一個新的Promise對象返回. ③:throw一個同步異常,then方法將返回一個rejected狀態(tài)的Promise,值是該異常.
根據(jù)以上分析,代碼中的第一個then會返回一個值為2(1 * 2),狀態(tài)為resolved的Promise對象,于第二個then輸出的值為2.第二個then中沒有返回值,因此將返回默認的undefined,于是在第三個then中輸出的undefined.第三個then和第四個then中分別返回一個狀態(tài)是resloved的Promise和一個狀態(tài)是rejected的Promise,依次由第四個then中的成功回調(diào)函數(shù)和第五個then中的失敗回調(diào)函數(shù)處理.
5.Promise then()回調(diào)異步性.
let p = new Promise((resolve, reject) => { resolve("成功!"); }); p.then(value => { console.log(value); }); console.log("誰先執(zhí)行?")
控制臺輸出:
"誰先執(zhí)行?" "成功!"
Promise接受的函數(shù)參數(shù)是同步執(zhí)行的,但是then方法中的回調(diào)函數(shù)則是異步的,因此,成功!會在后面輸出.
6.Promise中的異常.
let p1 = new Promise((resolve, reject) => { foo.bar(); resolve(1); }); p1.then(value => { console.log(`p1 then value: ${value}`); }, err => { console.log(`p1 then err: ${err}`); }).then(value => { console.log(`p1 then then value: ${value}`); }, err => { console.log(`p1 then then err: ${err}`); }); let p2 = new Promise((resolve, reject) => { resolve(2); }); p2.then(value => { console.log(`p2 then value: ${value}`); foo.bar(); }, err => { console.log(`p2 then err: ${err}`); }).then(value => { console.log(`p2 then then value: ${value}`); }, err => { console.log(`p2 then then err: ${err}`); return 1; }).then(value => { console.log(`p2 then then then value: ${value}`); }, err => { console.log(`p2 then then then err: ${err}`); });
控制臺輸出:
p1 then err: ReferenceError: foo is not defined p2 then value: 2 p1 then then value: undefined p2 then then err: ReferenceError: foo is not defined p2 then then then value: 1
Promise中的異常由then參數(shù)中的第二個回調(diào)函數(shù)(Promise執(zhí)行失敗的回調(diào))處理,異常信息將作為Promise的值.異常一旦得到處理,then返回后續(xù)的Promise對象將恢復(fù)正常,并會被Promise執(zhí)行成功的回調(diào)函數(shù)處理.另外,需要注意p1,p2多級then的回調(diào)函數(shù)是交替執(zhí)行的,這正是由Promise then回調(diào)的異步性決定的.
7.Promise.reslove().
let p1 = Promise.resolve(1); let p2 = Promise.resolve(p1); let p3 = new Promise((resolve, reject) => { resolve(1); }); let p4 = new Promise((resolve, reject) => { resolve(p1); }); console.log(p1 === p2); console.log(p1 === p3); console.log(p1 === p4); console.log(p3 === p4); p4.then(value => { console.log(`p4=${value}`) }); p2.then(value => { console.log(`p2=${value}`) }); p1.then(value => { console.log(`p1=${value}`) });
控制臺輸出:
true false false false p2=1 p1=1 p4=1
Promise.resolve(...) 可以接受一個值或者是一個Promise對象作為參數(shù).當參數(shù)是普通值時,它返回一個resolved狀態(tài)的Promise對象,對象的值就是這個參數(shù);當參數(shù)是一個Promise對象時,它直接返回這個Promise參數(shù).所以p1===p2.但通過new創(chuàng)建的Promise對象都是一個新的對象,所以后面三個比較結(jié)果都是false.另外,為什么p4的then最先調(diào)用,但是在控制臺上是最后輸出結(jié)果的呢?因為p4中resolve接受的參數(shù)是一個Promise對象p1,reslove會對p1進行解析,獲取p1的狀態(tài)和值,但是這個過程是異步的.
8.resolve v reject.
let p1 = new Promise((resolve, reject) => { resolve(Promise.resolve("resolve")); }); let p2 = new Promise((resolve, reject) => { resolve(Promise.reject("reject")); }); let p3 = new Promise((resolve, reject) => { reject(Promise.resolve("resolve")); }); p1.then(value => { console.log(`p1 fulfilled: ${value}`); }, err => { console.log(`p1 rejected: ${err}`); }); p2.then(value => { console.log(`p2 fulfilled: ${value}`); }, err => { console.log(`p2 rejected: ${err}`); }); p3.then(value => { console.log(`p3 fulfilled: ${value}`); }, err => { console.log(`p3 rejected: ${err}`); });
控制臺輸出:
p3 rejected: [object Promise] p1 fulfilled: resolve p2 rejected: reject
Promise回調(diào)函數(shù)中的第一個參數(shù)resolve,會對Promise執(zhí)行解析,即resolve的參數(shù)是Promise對象時,resolve會解析獲取這個Promise對象的狀態(tài)和值,但這個過程是異步的.p1解析后,獲取到Promise對象的狀態(tài)是resolved,因此第一個回調(diào)被執(zhí)行也就是獲取value的回調(diào);p2解析后,獲取到Promise對象的狀態(tài)rejected,因此rejected回調(diào)執(zhí)行.但Promise回調(diào)函數(shù)中的第二個參數(shù)reject不具備解析能力,reject的參數(shù)會直接傳遞給then方法中的rejected回調(diào),因此,即使p3 reject接受了一個resolved狀態(tài)的Promise,then方法中調(diào)用的依然是rejected,并且參數(shù)就是reject接受到的Promise對象.
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/84427.html
摘要:則是把類似的異步處理對象和處理規(guī)則進行規(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é)果。有了對象,就可以將異步操作以同步操作的流程表達出來,避免了層層嵌套的回調(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)建一個新的。這個是剛剛鏈式調(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,只知道它是什么(鏈式調(diào)用,用于請求的后返回值得操作之類的),大概怎么用,卻沒有深入了解。 起因:(在參考了廖雪峰的prom...
摘要:執(zhí)行,輸出,宏任務(wù)執(zhí)行結(jié)束。到此為止,第一輪事件循環(huán)結(jié)束。參考入門阮一峰系列之我們來聊聊一道關(guān)于應(yīng)用的面試題阿里前端測試題關(guān)于中函數(shù)的理解與應(yīng)用這一次,徹底弄懂執(zhí)行機制一個面試題原生的所有方法介紹附一道應(yīng)用場景題目異步流程控制 說明 最近在復(fù)習(xí) Promise 的知識,所以就做了一些題,這里挑出幾道題,大家一起看看吧。 題目一 const promise = new Promise((...
摘要:反之,操作失敗,對象由狀態(tài)轉(zhuǎn)換為狀態(tài),此時回調(diào)函數(shù)會執(zhí)行方法。這里需要注意的是,雖然在之后便執(zhí)行了方法,但是并不是意味著往后的對象不執(zhí)行了,其他的還是對象還是要執(zhí)行的,只是不會再調(diào)用函數(shù)。 在 掘金上看見一篇寫promise的文章,感覺作者寫的很棒,文章鏈接在這:八段代碼徹底掌握 Promise ??赐曛蟾杏X學(xué)到了很多,所以又重新把JavaScript Promise迷你書(中文版)...
閱讀 2849·2021-10-11 11:08
閱讀 1556·2021-09-30 09:48
閱讀 1118·2021-09-22 15:29
閱讀 1100·2019-08-30 15:54
閱讀 1059·2019-08-29 15:19
閱讀 591·2019-08-29 13:12
閱讀 3235·2019-08-26 13:53
閱讀 1035·2019-08-26 13:28