ES6中的Promise详解
Promise 在 JavaScript 中很早就有各种的开源实现,ES6 将其纳入了官方标准,提供了原生 api 支持,使用更加便捷。
定义
Promise 是一个对象,它用来标识 JavaScript 中异步操作的状态(pending, resolve, reject)及结果(data)。
从控制台打印出来一个Promise 对象来看下

可以看到,它是一个构造函数,既有属于自己私有的 resolve, reject, all, race等方法,也有protype 原型上的 then, catch等方法。
基本用法
- 模拟问题:3秒后请求完成,返回数据res.data
var p = new Promise((resolve, reject) => {
setTimeout(() => {
resolve('res.data');
}, 3000);
});
p.then((val) => {
console.log(val);
// 'res.data'
});
console.log(p);
// [object Promise]
Promise.resolve() 的用法
Promise.resolve()方法可以将现有对象转为Promise 对象。
var p = Promise.resolve($.ajax('/something.data'));
p.then((val) => {console.log(val)});
它等价于
var p = new Promise(resolve => {
resolve($.ajax('/something.data'))
});
p.then((val) => {console.log(val)});
Promise.reject() 用法
此方法和Promise.resolve()方法类似,除了rejecet 代表状态为 Rejected,不多说。
Promise.all() 用法
用于将多个Promise 实例包装成一个新的 Promise实例,参数为一组 Promise 实例组成的数组。
var p = Promise.all([p1,p2,p3]);
当 p1, p2, p3 状态都 Resolved 的时候,p 的状态才会 Resolved;只要有一个实例 Rejected ,此时第一个被 Rejected 的实例的返回值就会传递给 P 的回调函数。
应用场景:假设有一个接口,需要其它两个接口的数据作为参数,此时就要等那两个接口完成后才能执行请求。
var p1 = new Promise((resolve, reject) => {
setTimeout(resolve, 1000, 'P1');
});
var p2 = new Promise((resolve, reject) => {
setTimeout(resolve, 2000, 'P2');
});
// 同时执行p1和p2,并在它们都完成后执行then:
Promise.all([p1, p2]).then((results) => {
console.log(results); // 获得一个Array: ['P1', 'P2']
});
Promise.race() 用法
和Promise.all 类似,区别是 Promise.race() 只要监听到其中某一个实例改变状态,它的状态就跟着改变,并将那个改变状态实例的返回值传递给回调函数。
应用场景: 可以通过多个异步任务来进行容错处理,多个接口返回同样的数据,只要有一个接口生效返回数据即可。
Promise.prototype.then()
then 方法是定义在 Promise 的原型对象上的,作用是为 Promise 实例添加状态改变时的回调函数;
then() 返回一个新的Promise 实例,因此可以支持链式写法。
链式写法的一个例子//来自廖雪峰
// 0.5秒后返回input*input的计算结果:
function multiply(input) {
return new Promise((resolve, reject) => {
console.log('calculating ' + input + ' x ' + input + '...');
setTimeout(resolve, 500, input * input);
});
}
// 0.5秒后返回input+input的计算结果:
function add(input) {
return new Promise((resolve, reject) => {
console.log('calculating ' + input + ' + ' + input + '...');
setTimeout(resolve, 500, input + input);
});
}
var p = new Promise((resolve, reject) => {
console.log('start new Promise...');
resolve(123);
});
p.then(multiply)
.then(add)
.then(multiply)
.then(add)
.then(function (result) {
console.log('Got value: ' + result);
});
Promise.prototype.catch()
catch 方法是一个语法糖,看下面代码就明白了,用于指定发生错误时的回调函数。
var p = new Promise((resolve, rejecet) => {
if (...) {resolve()};
else {reject()};
})
p.then((val) => {
console.log('resolve:', val);
}).catch((err) => console.log('reject:', err));
// 等同于
p.then((data) => {
console.log(data);
}, (err) => {
console.log(err);
})
// 后一种写法更好,语义更清晰,第一种方法在第一个函数里面出错的话时在第二个函数里监听不到变化的。
Promise.try()
实际开发中,经常遇到一种情况:不知道或者不想区分,函数 f 是同步函数还是异步操作,但是想用 Promise 来处理它。因为这样就可以不管f是否包含异步操作,都用 then 方法指定下一步流程,用 catch 方法处理 f 抛出的错误。
- 第一种方法,缺陷是不能识别同步请求。
const f = () => console.log('now');
Promise.resolve().then(f);
console.log('next');
// next
// now
- new Promise() 写法
const f = () => console.log('now');
(
() => new Promise(
resolve => resolve(f())
)
)();
console.log('next');
// now
// next
- Promise.try 写法,替代new Promise() 方法,更简洁。
const f = () => console.log('now');
Promise.try(f);
console.log('next');
// now
// next
总结
两个特点
- 状态不受外界影响,只有异步操作的结果会影响到它,pending(进行中),reject(已失败),resolved(已完成)
- 状态只能改变一次
感受:
- promise 首先是一个构造函数,所以需要new 出来一个实例来使用
- 像是一个 ajax 函数外面加了一层包裹层,封装了一下下,实现了代码层面的同步效果
- 很有意思~(废话)
- 缺点也很明显,就是代码语义化不够,一眼看去都是Promise 的 API,then catch 等等,不能很快明白代码究竟想表达什么意思,这也是 async 函数出现的原因,async ,可能是异步操作的终极方案了。
ES6中的Promise详解的更多相关文章
- js中的promise详解
一 概述 Promise是异步编程的一种解决方案,可以替代传统的解决方案--回调函数和事件.ES6统一了用法,并原生提供了Promise对象.作为对象,Promise有一下两个特点: (1)对象的 ...
- Javascript中prototype属性详解 (存)
Javascript中prototype属性详解 在典型的面向对象的语言中,如java,都存在类(class)的概念,类就是对象的模板,对象就是类的实例.但是在Javascript语言体系中,是不 ...
- php中关于引用(&)详解
php中关于引用(&)详解 php的引用(就是在变量或者函数.对象等前面加上&符号) 在PHP 中引用的意思是:不同的变量名访问同一个变量内容. 与C语言中的指针是有差别的.C语言中的 ...
- JavaScript正则表达式详解(二)JavaScript中正则表达式函数详解
二.JavaScript中正则表达式函数详解(exec, test, match, replace, search, split) 1.使用正则表达式的方法去匹配查找字符串 1.1. exec方法详解 ...
- AngularJS select中ngOptions用法详解
AngularJS select中ngOptions用法详解 一.用法 ngOption针对不同类型的数据源有不同的用法,主要体现在数组和对象上. 数组: label for value in a ...
- 【转载】C/C++中extern关键字详解
1 基本解释:extern可以置于变量或者函数前,以标示变量或者函数的定义在别的文件中,提示编译器遇到此变量和函数时在其他模块中寻找其定义.此外extern也可用来进行链接指定. 也就是说extern ...
- oracle中imp命令详解 .
转自http://www.cnblogs.com/songdavid/articles/2435439.html oracle中imp命令详解 Oracle的导入实用程序(Import utility ...
- Android中Service(服务)详解
http://blog.csdn.net/ryantang03/article/details/7770939 Android中Service(服务)详解 标签: serviceandroidappl ...
- python中threading模块详解(一)
python中threading模块详解(一) 来源 http://blog.chinaunix.net/uid-27571599-id-3484048.html threading提供了一个比thr ...
随机推荐
- strong & weak 的理解
import "ViewController.h" @interface ViewController () /*weak*/ @property (nonatomic,weak) ...
- 【最小树形图(奇怪的kruskal)】【SCOI 2012】【bzoj 2753】滑雪与时间胶囊
2753: [SCOI2012]滑雪与时间胶囊 Time Limit: 50 Sec Memory Limit: 128 MB Submit: 1621 Solved: 570 Description ...
- window对象属性alert、confirm、prompt怎么使用?
window对象属性alert.confirm.prompt怎么使用? 一.总结 1.参数依次复杂,返回值依次复杂,但是感觉都是一一继承的,所以很好想也很好写. 二.window对象alert.con ...
- MUI简介-最接近原生App体验的前端框架
MUI简介-最接近原生App体验的前端框架 一.总结 一句话总结:最接近原生App体验的前端框架 二.多端发布 – 开发一套代码,发布六个平台 真正彻底的跨平台开发,不是简单的跨iOS和Android ...
- poj 2594 Treasure Exploration 二分图匹配
点击打开链接题目链接 Treasure Exploration Time Limit: 6000MS Memory Limit: 65536K Total Submissions: 7215 ...
- eclipse上springCloud分布式微服务搭建-干货
一.创建maven父工程(pom) pom.xml如下: eureka: client: registerWithEureka:false fetchRegistry:false serviceUrl ...
- POJ 2418-Hardwood Species(map)
Hardwood Species Time Limit: 10000MS Memory Limit: 65536K Total Submissions: 18770 Accepted: 740 ...
- 获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录
获取全局上下文(getApplicationContext)_创建Shared Preference工具类_实现自动登录 ===========================获取全局上下文(getA ...
- react中属性默认值是true?
看到项目代码中 return ( <MyWebView state="Login" title="登录app" ref="login" ...
- HTTP协议中的报文格式
按照传输过程,HTTP 报文分为请求报文和响应报文.请求报文和响应报文的结构差不多,这里只对 HTTP 请求报文做一个总结.HTTP 请求报文由 请求行.请求头.请求体(请求数据).空行 四个部分组成 ...