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 ...
随机推荐
- JNI:no implementation found in native...
一 javah引发的问题 BUG:D/dalvikvm( 1704): Trying to load lib /data/data/com.ulang/lib/libulangaudio.so 0x ...
- php实现把数组排成最小的数(核心是排序)(看别人的代码其实也没那么难)(把php代码也看一下)(implode("",$numbers);)(usort)
php实现把数组排成最小的数(核心是排序)(看别人的代码其实也没那么难)(把php代码也看一下)(implode("",$numbers);)(usort) 一.总结 核心是排序 ...
- udp绑定信息
1. udp网络程序-端口问题 会变的端口号 重新运行多次脚本,然后在“网络调试助手”中,看到的现象如下: 说明: 每重新运行一次网络程序,上图中红圈中的数字,不一样的原因在于,这个数字标识这个网络程 ...
- 关于android 怎样安装 assets文件下的apk
在自己的app中安装assets文件夹下的apk文件 public class MainActivity extends Activity { Context mContext; @Override ...
- 使用搜狐Sendcloud的Webapi发送邮件:Jodd和Apache Httpclient
最近,在使用搜狐Sendcloud发邮件. Sendcloud提供http格式的webapi,方便地发送邮件,当然是要付费的. 很早之前,http工具一直用Httpclient,后来觉得jodd ...
- 三天打渔,俩天晒网(C++实现)
#include <iostream> using namespace std; int leap (int a) { if (a%4==0%a%100!=0||a%400==0) ...
- [Angular] Export directive functionalities by using 'exportAs'
Directive ables to change component behaives and lookings. Directive can also export some APIs which ...
- [React] Pass Data To Event Handlers with Partial Function Application
In this lesson we’ll see how to pass an item’s id value in an event handler and get the state to ref ...
- Go 快速入门
入门 Go 语言需要多久?答案是 -- 读完这篇文章的时间!不妨找一个周末的下午,踏上 Go 之旅吧! 更新记录: 2016.12.12: 完成重制 2016.11.02: 增加重点理解和参考链接 2 ...
- web项目的WEB-INF目录
WEB-INF是Java的WEB应用的安全目录.所谓安全就是客户端无法访问,只有服务端可以访问的目录. 如果想在页面中直接访问其中的文件,必须通过web.xml文件对要访问的文件进行相应映射才能访问. ...