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

