一文總結(jié)JavaScript中Promise遇到的問題
什么是Promise
國內(nèi)比較流行的看法:
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強大。它由社區(qū)最早提出和實現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise
對象。
Promise 真正的規(guī)范,推薦大家看看這篇長文:promisesaplus.com/
1. 是否可以使用return
代替 resolve
不可以,無法實現(xiàn)鏈?zhǔn)秸{(diào)用,且不符合規(guī)范。
示例:
const testReturn = (a:boolean):Promise<any> =>{ return new Promise((resolve,reject)=>{ if(a){ return 'this is return'; resolve('true'); console.log('this will not be exec'); throw new Error('error'); }else{ reject('false'); } }) }
執(zhí)行結(jié)果:
~ ts-node return.ts Promise { <pending> }
- 無法改變狀態(tài)
無法鏈?zhǔn)秸{(diào)用
2. 使用throw還是reject?
答案: 使用reject
而不是throw
示例1:不會被catch的throw Error
const testReturn = (a:boolean):Promise<any> =>{ return new Promise((resolve,reject)=>{ if(a){ resolve('true'); console.log('this will be exec'); throw new Error('error'); }else{ reject('false'); } }) } console.log(testReturn(true));
執(zhí)行結(jié)果
~/chen/FE/winSep/codes/javascript/es6promise/src ts-node return.ts this will be exec Promise { 'true' }
解釋:
Promise的構(gòu)造函數(shù),以及被 then
調(diào)用執(zhí)行的函數(shù)基本上都可以認(rèn)為是在 try…catch
代碼塊中執(zhí)行的,所以在這些代碼中即使使用 throw
,程序本身也不會因為異常而終止。Promise的狀態(tài)也不會發(fā)生改變。
示例2:不使用reject而使用throw
如果在Promise中使用 throw
語句的話,會被 try...catch
住,最終promise對象也變?yōu)镽ejected狀態(tài)。
var promise = new Promise(function(resolve, reject){ throw new Error("message"); }); promise.catch(function(error){ console.error(error);// => "message" });
運行
Error: message
代碼像這樣其實運行時倒也不會有什么問題,但是如果想把 promise
設(shè)置為Rejected狀態(tài)的話,使用 reject
方法則更顯得合理。
所以上面的代碼可以改寫為下面這樣。
var promise = new Promise(function(resolve, reject){ reject(new Error("message")); }); promise.catch(function(error){ console.error(error);// => "message" })
總結(jié):如果在Promise中使用 throw
語句的話,會被 try...catch
住,最終promise對象也變?yōu)镽ejected狀態(tài)。
3. Promise的執(zhí)行時間
3.1 resolve后面的代碼會不會被執(zhí)行?
當(dāng)沒有Error
的時候, resolve
會將Promise.then
放在微任務(wù)隊列中,當(dāng)所有的宏任務(wù)執(zhí)行結(jié)束的時候,執(zhí)行微任務(wù)隊列。
const testReturn = (a:boolean):Promise<any> =>{ return new Promise((resolve,reject)=>{ if(a){ resolve('exec true'); console.log('this will be exec'); // throw new Error('error'); }else{ reject('false'); } }) } testReturn(true).then(str=>{ console.log(str); })
執(zhí)行結(jié)果
this will be exec exec true
當(dāng)有Error
的時候,Error
后面的代碼不會被執(zhí)行,但是Promise
的結(jié)果依舊是fulfilled
const testReturn = (a:boolean):Promise<any> =>{ return new Promise((resolve,reject)=>{ if(a){ resolve('exec true'); console.log('this will be exec'); throw new Error('error'); console.log('this will not be exec') }else{ reject('false'); } }) } testReturn(true).then(str=>{ console.log(str); // console.log(testReturn) }).catch(err=>{ console.log('err: ',err); })
執(zhí)行結(jié)果
this will be exec
exec true
3.2 當(dāng)Promise遇到setTimeout
看例子:
const testReturn = (a:boolean):Promise<any> =>{ return new Promise((resolve,reject)=>{ setTimeout(()=>{ if(a){ resolve('exec true'); console.log('this will be second exec'); }else{ reject('false'); } }) console.log('this will first be execd'); }) } testReturn(true).then(str=>{ console.log(str); // console.log(testReturn) }).catch(err=>{ console.log('err: ',err); })
結(jié)果
this will first be execd this will be second exec exec true
解釋:
時間 | 宏任務(wù)隊列 | 微任務(wù)隊列 |
---|---|---|
1 | console.log('this will first be execd') | |
2 | setTimeout | |
3 | resolve('exec true'); //延遲:因為宏任務(wù)沒有執(zhí)行完 | |
4 | console.log('this will be second exec'); |
最終執(zhí)行順序:
1->2->4(宏任務(wù)結(jié)束)->3(微任務(wù)結(jié)束)
3.3 async/await 與Promise
一句話總結(jié): await
等的就是一個Promise
。如果等的不是Promise
,那加了await
和不加沒區(qū)別
將常規(guī)的回調(diào)轉(zhuǎn)變?yōu)?code>Promise的方法
function util(args,callback){ if(err){ return callback(err); }else{ return callback(); } } //調(diào)用 util(args,(err)=>{ if(err){ }else{ } }) //Promisify function utilPromise(args){ return new Promise((resolve,reject)=>{ if(err){ reject(err) }else{ resolve(); } }) } //調(diào)用 utilPromise.then().catch()
將
Promise
轉(zhuǎn)換為async/await
的方法
async init(){ try{ await utilPromise();//resolve狀態(tài) }catch(e){ throw new Error(e); //reject狀態(tài) } }
到此這篇關(guān)于一文總結(jié)JavaScript中Promise遇到的問題的文章就介紹到這了,更多相關(guān)JavaScript Promise內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
JavaScript實現(xiàn)可拖拽的拖動層Div實例
這篇文章主要介紹了JavaScript實現(xiàn)可拖拽的拖動層Div的方法,拖拽頁面中的div塊可實現(xiàn)div塊按照拖動軌跡移動的效果,涉及javascript鼠標(biāo)事件、頁面元素樣式結(jié)合事件函數(shù)動態(tài)操作的相關(guān)技巧,需要的朋友可以參考下2015-08-08僅Firefox中鏈接A無法實現(xiàn)模擬點擊以觸發(fā)其默認(rèn)行為
偶然發(fā)現(xiàn)之前寫的事件模塊在Firefox5中無法觸發(fā)A的默認(rèn)行為了。IE/Opera/Firefox5中A具有click方法,因此模擬點擊直接調(diào)用click方法即可。2011-07-07