本文作者: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.

从问题来看

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

解释:

时间 宏任务队列 微任务队列
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(微任务结束)

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状态
}
}

Promise最佳实践(转)的更多相关文章

  1. 【转】jQuery最佳实践

    上周,我整理了<jQuery设计思想>. 那篇文章是一篇入门教程,从设计思想的角度,讲解"怎么使用jQuery".今天的文章则是更进一步,讲解"如何用好jQu ...

  2. JavaScript best practices JS最佳实践

    JavaScript best practices JS最佳实践 0 简介 最佳实践起初比较棘手,但最终会让你发现这是非常明智之举. 1.合理命名方法及变量名,简洁且可读 var someItem = ...

  3. nodejs 实践:express 最佳实践(三) express 解析

    nodejs 实践:express 最佳实践(三) express 解析 nodejs 发展很快,从 npm 上面的包托管数量就可以看出来.不过从另一方面来看,也是反映了 nodejs 的基础不稳固, ...

  4. JQuery系列(7) - JQuery最佳实践

    上篇文章是一篇入门教程,从设计思想的角度,讲解"怎么使用jQuery".今天的文章则是更进一步,讲解"如何用好jQuery". 我主要参考了Addy Osman ...

  5. Typescript 最佳实践

    文章列表: <一>大话 TypeScript 基本类型 <二>大话 Typescript 枚举 <三>大话 Typescript 接口 <四>大话 Ty ...

  6. ​结合异步模型,再次总结Netty多线程编码最佳实践

    更多技术分享可关注我 前言 本文重点总结Netty多线程的一些编码最佳实践和注意事项,并且顺便对Netty的线程调度模型,和异步模型做了一个汇总.原文:​​结合异步模型,再次总结Netty多线程编码最 ...

  7. uni-app 中实现 onLaunch 异步回调后执行 onLoad 最佳实践

    前言 好久没写博客了,由于公司业务需要,最近接触uiapp比较多,一直想着输出一些相关的文章.正好最近时间富余,有机会来一波输出了. 问题描述 在使用 uni-app 开发项目时,会遇到需要在 onL ...

  8. 我的 React 最佳实践

    There are a thousand Hamlets in a thousand people's eyes. ----- 威廉·莎士比亚 免责声明:以下充满个人观点,辩证学习 React 目前开 ...

  9. ASP.NET跨平台最佳实践

    前言 八年的坚持敌不过领导的固执,最终还是不得不阔别已经成为我第二语言的C#,转战Java阵营.有过短暂的失落和迷茫,但技术转型真的没有想象中那么难.回头审视,其实单从语言本身来看,C#确实比Java ...

随机推荐

  1. RNAcentral 数据库简介

    RNAcentral 是EBI 开发的一个非编码RNA的数据库. 网址如下: http://rnacentral.org/ RNAcentral 整合了包括 Ensembl, GENCODE,Gree ...

  2. iOS: 控制UIView的外形

    #import <UIKit/UIKit.h> #import <QuartzCore/QuartzCore.h> @interface UIView (Shape) - (v ...

  3. XCODE 添加不同IOS版本的模拟器

    一.XCode->Preferences->Downloads, 可以下载模拟器.

  4. Objective-C语法之指针型参数

    main.m #import <Foundation/Foundation.h> /** * 测试指针型参数和普通参数的区别 * * @param a 指针型参数 * @param b 普 ...

  5. kuser_cmpxchg_check 原子操作

    对于ARM体系结构,每一个由用户态到内核态的中断或异常处理路径都经过kuser_cmpxchg_check,kuser_cmpxchg_check中检查被中断的地址是否大于TASK_SIZE:TASK ...

  6. 【RespberryPi】数码管

    http://blog.mangolovecarrot.net/2015/06/03/raspi-study0801/ 应该可以用两块74HC595来驱动显示8位数的数码管.

  7. 解决win8.1电脑无法安装手机驱动问题

    相信安装过win8.1的朋友都会有个问题,那就是自己的安卓手机怎么都连不上电脑,比如360助手.豌豆荚.91助手,都安不上驱动.下面几个简单步骤即可轻松解决. 1.首先声明,官方的驱动是完全支持win ...

  8. ispriter自动构建css-sprite

    优化你的网站: 当一个网站中的资源(比如:js文件.css文件.图片等)很多时必然影响用户访问速度,这时候你就需要做网站性能优化,你可以选择把资源分开放在不同的服务器上,因为一个资源服务器最多可以同时 ...

  9. 关于python 的空的__init__.py文件的作用,可不可以删除,到底有没有用?

    0.声明,本篇只讨论空__init__.py文件的情况,不顾前提非得说__init__.py文件里面也可以写东西的不在此讨论了范围之内,重点是个"空"字. 1.很多地方的文件夹都有 ...

  10. swift--浮点数转换成整数(四舍五入/直接截断)

    1,直接截取小数部分转换成整数 let i = Int(23.52536) print("输出是:\(i)") 2,四舍五入转换成证书 let q = lround(586.565 ...