Promise是异步编程的解决方案之一,它比传统的解决方案(回调函数和事件)更加合理和强大。
Promise:
1、可以说是一个容器,里面保存着某个未来才会结束的事件。
2、Promise是个对象,从它可以获取异步操作的消息。
Promise两个特点:
(1)对象状态不受外界影响。三种状态:Pending(进行中),fulfilled(已成功),rejected(已拒绝).只有异步操作的结果可以决定当前是哪一种转态,任何其他操作都无法改变这个状态。
(2)一旦状态改变就不会在变。只有两种改变方法:pending-->fulfilled,pending-->rejected.
注意:有了Promise对象,可以将异步操作以同步操作的流程表达出来。
利用Promise对象实现Ajax操作
var getJSON = function(url){
var promise = new Promise(function(resolve,reject){
var client = new XMLHttpRequest();
client.open('GET',url);
client.onreadystatechange = handler;
client.responseType = 'json';
client.setRequestHeader("Accept","application/json");
client.send();
function handler(){
if(this.readyState !==4){
return;
}
if(this.status === 200){
resolve(this.response);
}else{
reject(new Error(this.statusText);
}
};
});
return promise;
};
getJSON("/posts.json").then(function(json){
console.log('Contents:'+json);
},function(error){
console.log('出错了',error);
});
注意:resolve和reject的Promise是在本轮事件循环的末尾执行,总是晚于本轮循环的同步任务。
由上面的例子可以看出,后续操作最好放到then方法中,不要直接写在resolve或reject后面,最好在他们前面加上renturn瑜伽。因为调用resolve和reject后,Promise的使命就完成了。
Promise实例具有的方法
【1】Promise.prototype.then()
作用:为Promise实例添加状态改变时的回调函数。
这个方法可以包含两个参数;
参数1:resolved状态的回调函数。
参数2:rejected转态的回调函数。
then方法返回的是一个Promise实例,所以可以采用链式方法,链式方法可以指定一组按照次序调用的回调函数。前一个回调函数有可能返回的还是一个Promise对象(有异步操作),后一个回调函数会等待该Promise对象的状态发生变化,再被调用。
【2】Promise.prototype.catch()
可以说是then方法的别名,用来指定发生错误时的回调函数。
then方法的第二个参数是用来定义rejected的回调函数,但最好不这么写,始终用catch方法去捕捉错误比较好。
好的写法和不好的写法
then()和catch()方法
异步操作抛出错误,状态会被置为Rejected,之后调用catch方法指定的回调函数可以处理这个错误。then()方法中的指定回调函数在运行中抛出错误,也会被catch方法捕获。
then方法等价于catch方法的写法:
证明Promise状态一旦改变,不会再变化。
Promise在resolve语句后面再抛出错误,并不会被捕获,等于没有抛出。因为Promise的状态一旦改变,就会保持该状态,不会再改变了。
如果不指定catch方法,错误是不会捕获,也不会传递到外层代码。这个和传统的try,catch是不同的。
Node有个unhandleRejection事件,专门监听未捕获的reject错误。
【3】Promise.all()
Promise.all()方法中的参数不一定是数组,但必须具有Interator接口,并且返回的每个成员都是Promise实例。(但 常用的是数组)
var p = Promise.all([p1,p2,p3]);
p的状态由p1,p2,p3决定:
1、p1,p2,p3全变为fulfilled,p的状态会变为fulfilled。
2、p1,p2,p3中有一个变为rejected,p的状态就会变为rejected。
另一点:
如果参数的Promise实例自身定义了catch方法,那么它被rejected时并不会触发Promise.all()的catch方法。
例子:
(1)p2自己本身有catch,所以Promise.all()的catch捕获不到。
(2)p2自己本身不加catch,这样Promise.all()的catch才能捕获到。
【4】Promise.race()
和Promise.all()的不同之处是:参数有一个实例率先发生变化,相应的状态就会发生变化。
【5】Promise.resolve()
作用:将现有的对象转为Promise对象。
该方法的参数有四种情况:
1、参数是Promise实例。
此时Promise.resolve不用做任何修改,原封不动的返回这个实例即可。
2、参数是thenable对象
问:什么是thenable对象?
具有then方法的对象。
如:
let thenable = {
then:function(resolve,reject){
resolve(42);
}};
Promise.resolve方法会将对象转为Promise对象,然后可以立即执行thenable对象的then方法。
3、不具有then方法的对象或者根本不是对象
Promise.resolve()方法返回了一个新的Promise对象,状态为resolved。
并且该方法的参数会同时传给回调函数。
4、不带有任何参数
Promise.resolve方法允许在调用时不带有参数,而直接返回一个Resolved状态的Promise对象。所以想要得到一个Promise对象,最简单的方法就是直接调用Promise.resolve()。
【5】Promise.reject()
作用:返回一个新的Promise实例,状态为Rejected。
等价于
两个不在es6中,却很有用的方法
【1】done() 放在回调链的末尾,保证抛出任何可能出现的错误。它可以捕捉到任何可能出现的错误,并向全局抛出。
【2】finally() 用来指定不管Promise对象最后状态如何都会执行的操作。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。