一文總結(jié)JavaScript中Promise遇到的問題
什么是Promise
國內(nèi)比較流行的看法:
Promise 是異步編程的一種解決方案,比傳統(tǒng)的解決方案——回調(diào)函數(shù)和事件——更合理和更強(qiáng)大。它由社區(qū)最早提出和實(shí)現(xiàn),ES6 將其寫進(jìn)了語言標(biāo)準(zhǔn),統(tǒng)一了用法,原生提供了Promise
對(duì)象。
Promise 真正的規(guī)范,推薦大家看看這篇長(zhǎng)文:promisesaplus.com/
1. 是否可以使用return
代替 resolve
不可以,無法實(shí)現(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:不會(huì)被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
,程序本身也不會(huì)因?yàn)楫惓6K止。Promise的狀態(tài)也不會(huì)發(fā)生改變。
示例2:不使用reject而使用throw
如果在Promise中使用 throw
語句的話,會(huì)被 try...catch
住,最終promise對(duì)象也變?yōu)镽ejected狀態(tài)。
var promise = new Promise(function(resolve, reject){ throw new Error("message"); }); promise.catch(function(error){ console.error(error);// => "message" });
運(yùn)行
Error: message
代碼像這樣其實(shí)運(yùn)行時(shí)倒也不會(huì)有什么問題,但是如果想把 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
語句的話,會(huì)被 try...catch
住,最終promise對(duì)象也變?yōu)镽ejected狀態(tài)。
3. Promise的執(zhí)行時(shí)間
3.1 resolve后面的代碼會(huì)不會(huì)被執(zhí)行?
當(dāng)沒有Error
的時(shí)候, resolve
會(huì)將Promise.then
放在微任務(wù)隊(duì)列中,當(dāng)所有的宏任務(wù)執(zhí)行結(jié)束的時(shí)候,執(zhí)行微任務(wù)隊(duì)列。
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
的時(shí)候,Error
后面的代碼不會(huì)被執(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
解釋:
時(shí)間 | 宏任務(wù)隊(duì)列 | 微任務(wù)隊(duì)列 |
---|---|---|
1 | console.log('this will first be execd') | |
2 | setTimeout | |
3 | resolve('exec true'); //延遲:因?yàn)楹耆蝿?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
等的就是一個(gè)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)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
原生JavaScript實(shí)現(xiàn)瀑布流布局
這篇文章主要介紹了原生JavaScript實(shí)現(xiàn)瀑布流布局的相關(guān)資料,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2015-12-12JavaScript實(shí)現(xiàn)可拖拽的拖動(dòng)層Div實(shí)例
這篇文章主要介紹了JavaScript實(shí)現(xiàn)可拖拽的拖動(dòng)層Div的方法,拖拽頁面中的div塊可實(shí)現(xiàn)div塊按照拖動(dòng)軌跡移動(dòng)的效果,涉及javascript鼠標(biāo)事件、頁面元素樣式結(jié)合事件函數(shù)動(dòng)態(tài)操作的相關(guān)技巧,需要的朋友可以參考下2015-08-08javascript 對(duì)象比較實(shí)現(xiàn)代碼
js對(duì)象比較實(shí)現(xiàn)代碼。2009-04-04Javascript 對(duì)cookie操作詳解及實(shí)例
這篇文章主要介紹了Javascript 對(duì)cookie操作詳解及實(shí)例的相關(guān)資料,大家在開發(fā)網(wǎng)站的時(shí)候,都會(huì)用到cookie 這里就詳細(xì)介紹下,需要的朋友可以參考下2016-12-12僅Firefox中鏈接A無法實(shí)現(xiàn)模擬點(diǎn)擊以觸發(fā)其默認(rèn)行為
偶然發(fā)現(xiàn)之前寫的事件模塊在Firefox5中無法觸發(fā)A的默認(rèn)行為了。IE/Opera/Firefox5中A具有click方法,因此模擬點(diǎn)擊直接調(diào)用click方法即可。2011-07-07