ES6原生提供了Promise对象,代表了将来将要发生的事件,用来传递异步操作的消息。
两个特点
- Promise对象代表一个异步操作,有三种状态:
- pending:初始状态,不是成功或失败状态
- fulfilled(or resolved):意味着操作成功完成
- rejected:意味着操作失败
- Promise对象的状态改变,只有两种可能:从pending变为resolved和从pending变为rejected。只要这两种情况发生,状态就凝固了,不会再变,会一直保持这个结果。就算改变已经发生,再对promise对象添加回调函数,也会立即得到这个结果。这与事件(Event)完全不同,事件的特点是,如果你错过了它,再去监听,是得不到结果的。
Promise创建
var promise = new Promise(function(resolve,reject){
//异步处理
//处理结束后,调用resolve或reject
});
Promise构造函数包含一个参数和一个带有resolve(解析)和reject(拒绝)两个参数的回调。在回调中执行一些操作,如果一切都正常,则调回resolve,否则调用reject。
function goods(name){
return new Promise(function (resolve,reject){
if(name == 'apple'){
resolve('苹果');
}else{
reject('不是苹果');
}
})
}
goods('orange').then(
(text)=>{console.log(text)},
(text)=>{console.log(text)}
)
对于已经实例化的promise对象,可以调用promise.then()方法,传递resolve和reject()方法作为回调。
promise.then(onFulfilled,onRejected)可以简化为:
promise.then(onFulfilled).catch(onRejected)
reject()方法的参数通常是Error对象的实例,而resolve()方法的参数除了正常的值外,还可能是另一个promise实例。
then的链式写法
Promise.prototype.then()方法返回的是一个新的Promise对象,因此可以采用链式写法。
getJSON('/post.json').then(function(){
return json.post;
}).then(function(){
});
第一个回调函数完成之后,会返回结果作为参数,传入第二个回调函数。如果前一个回调函数返回的是Promise对象,这时后一个回调函数就会等待该Promise对象有了运行结果,才会进一步调用。
Promise.all方法,Promise.race方法
Promise.all用于将多个Promise实例,包装成一个新的Promise实例。
var p = Promise.all([p1,p2,p3]);
Promise.all接受一个数组作为参数,p1、p2、p3都是Promise对象的实例。
p的状态由p1、p2、p3决定,分成两种情况。
- 只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
- 只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
Promise.race 方法同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
var p = Promise.race([p1,p2,p3]);
只要p1、p2、p3之中有一个实例率先改变状态,p的状态就跟着改变。那个率先改变的Promise实例的返回值,就传递给p的返回值。
Promise实现ajax
window.$ajax = function(url,method,body){
return new Promise((resolve,reject)=>{
var request = new XMLHttpRequest()
request.open(method,url)
request.onreadystatechange = ()=>{
if(readyState === 4){
if(request.status === 200){
resolve()
}else{
reject()
}
}
}
request.send(body)
})
}
window.$ajax(url,method,body).then(()=>{}).catch(()=>{})