一文总结JavaScript中Promise遇到的问题
作者:白哥学前端
什么是Promise
国内比较流行的看法:
Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise
对象。
Promise 真正的规范,推荐大家看看这篇长文:promisesaplus.com/
1. 是否可以使用return
代替 resolve
不可以,无法实现链式调用,且不符合规范。
示例:
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'); } }) }
执行结果:
~ ts-node return.ts Promise { <pending> }
- 无法改变状态
无法链式调用
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));
执行结果
~/chen/FE/winSep/codes/javascript/es6promise/src ts-node return.ts this will be exec Promise { 'true' }
解释:
Promise的构造函数,以及被 then
调用执行的函数基本上都可以认为是在 try…catch
代码块中执行的,所以在这些代码中即使使用 throw
,程序本身也不会因为异常而终止。Promise的状态也不会发生改变。
示例2:不使用reject而使用throw
如果在Promise中使用 throw
语句的话,会被 try...catch
住,最终promise对象也变为Rejected状态。
var promise = new Promise(function(resolve, reject){ throw new Error("message"); }); promise.catch(function(error){ console.error(error);// => "message" });
运行
Error: message
代码像这样其实运行时倒也不会有什么问题,但是如果想把 promise
设置为Rejected状态的话,使用 reject
方法则更显得合理。
所以上面的代码可以改写为下面这样。
var promise = new Promise(function(resolve, reject){ reject(new Error("message")); }); promise.catch(function(error){ console.error(error);// => "message" })
总结:如果在Promise中使用 throw
语句的话,会被 try...catch
住,最终promise对象也变为Rejected状态。
3. Promise的执行时间
3.1 resolve后面的代码会不会被执行?
当没有Error
的时候, resolve
会将Promise.then
放在微任务队列中,当所有的宏任务执行结束的时候,执行微任务队列。
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); })
执行结果
this will be exec exec true
当有Error
的时候,Error
后面的代码不会被执行,但是Promise
的结果依旧是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); })
执行结果
this will be exec
exec true
3.2 当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); })
结果
this will first be execd this will be second exec exec true
解释:
时间 | 宏任务队列 | 微任务队列 |
---|---|---|
1 | console.log('this will first be execd') | |
2 | setTimeout | |
3 | resolve('exec true'); //延迟:因为宏任务没有执行完 | |
4 | console.log('this will be second exec'); |
最终执行顺序:
1->2->4(宏任务结束)->3(微任务结束)
3.3 async/await 与Promise
一句话总结: await
等的就是一个Promise
。如果等的不是Promise
,那加了await
和不加没区别
将常规的回调转变为
Promise
的方法
function util(args,callback){ if(err){ return callback(err); }else{ return callback(); } } //调用 util(args,(err)=>{ if(err){ }else{ } }) //Promisify function utilPromise(args){ return new Promise((resolve,reject)=>{ if(err){ reject(err) }else{ resolve(); } }) } //调用 utilPromise.then().catch()
将
Promise
转换为async/await
的方法
async init(){ try{ await utilPromise();//resolve状态 }catch(e){ throw new Error(e); //reject状态 } }
到此这篇关于一文总结JavaScript中Promise遇到的问题的文章就介绍到这了,更多相关JavaScript Promise内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!