Promise最佳实践(转)

本文作者:IMWeb dekuchen 原文出处:IMWeb社区 未经同意,禁止转载

有关Promise的几个问题

基础概念

一:什么是Promise

国内比较流行的看法:

阮一峰: Promise 对象

Promise 是异步编程的一种解决方案,比传统的解决方案——回调函数和事件——更合理和更强大。它由社区最早提出和实现,ES6 将其写进了语言标准,统一了用法,原生提供了Promise对象。

Promise 真正的规范,一篇长文。

https://promisesaplus.com/

截取几段:

Terminology

  1. “promise” is an object or function with a then method whose behavior conforms to this specification.
  2. “thenable” is an object or function that defines a then method.
  3. “value” is any legal JavaScript value (including undefined, a thenable, or a promise).
  4. “exception” is a value that is thrown using the throw statement.
  5. “reason” is a value that indicates why a promise was rejected.

promise-states

从问题来看

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'); } }) } 

执行结果:

 ~/chen/FE/winSep/codes/javascript/es6promise/src  ts-node return.ts
Promise { <pending> }
  1. 无法改变状态
  2. 无法链式调用

2. 使用throw还是reject?

答案: 使用reject而不是throw

示例:不会被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的状态也不会发生改变。

示例:不使用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状态。

2. Promise的执行时间

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

当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

解释:

时间宏任务队列微任务队列
1console.log('this will first be execd') 
2setTimeout 
3 resolve('exec true');//延迟:因为宏任务没有执行完
4console.log('this will be second exec'); 
  

最终执行顺序:

1->2->4(宏任务结束)->3(微任务结束)

async/await 与Promise

一句话总结:await等的就是一个Promise。如果等的不是Promise,那加了await和不加没区别

  1. 将常规的回调转变为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() 
  1. Promise转换为async/await的方法
async init(){
    try{
        await utilPromise();//resolve状态 }catch(e){ throw new Error(e); //reject状态 } }

转载于:https://www.cnblogs.com/sunshq/p/9303909.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值