Promise对象是一种异步编程的解决方案,比传统的解决方案——会掉函数和事件——更合理和强大。
Promise有三种状态:pending(进行中)、Resolved(Fulfilled,已完成)和Rejected(已失败);而且状态一旦改变,就不会再发生改变,Promise对象的状态只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生了,状态就凝固了,不会再变了。Promise有一些缺点,就是无法取消,一旦新建它就会执行,无法中途取消;其次如果不设置回调函数,Promise内部抛出的错误,不会反应到外部;第三Pending状态时,无法得知目前进展到哪一个阶段。
基本用法
Promise构造函数接受一个函数作为参数,该函数参数分别是resolve和reject方法。如果成功,则用resolve将Promise的状态改为成功,即从Pending变为resolved;如果异步失败,则从Pending改为rejected。
基本用法
var promise = new Promise(function(resolve, reject){
if(/*异步操作成功*/){
resolve(value);
} else{
reject(error);
}
});
promise.then(function(value){
//success
}, function(value){
//failure
});
一个简单实用的例子
function timeout(ms){
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
timeout(100).then(()=>{
console.log('done');
})
如果用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.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.error('出错了', error);
})
在resolve的方法参数除了正常值以为,还可以能是另一个Promise实例。
Promise的链式操作:Promise.prototype.then
Promise.prototype.then返回的是一个新的Promise对象,因此可以写成链式的。
getJSON("/posts.json").then(function(json){
return json.post;
}).then(function(){
//proceed
})
上面的代码指定了两个回调函数,第一个回调函数完成以后,会将结果作为参数传入到第二个回调函数。
如果第一个回调函数返回的是Promise对象,这样后一个函数调用就将等待该Promise对象有了运行结果,才会进一步调用。
getJSON("/post/1.json").then(function(post){
return getJSON(post.commentURL);
}).then(function(comments){
//对comments进行处理
})
捕捉错误:Promise.prototype.catch方法
Promise.prototype.catch其实是对Promise.prototype.then(null, rejection)的调用,用于指定发生错误时的回调函数。
Promise.prototype.catch 对错误具有“冒泡”性质,会一直向后传递,直到被捕获,也就是错我总是被下一个catch语句捕获。
getJSON("/post/1.json").then(function(post) {
return getJSON(post.commentURL);
}).then(function(comments) {
// some code
}).catch(function(error) {
// 处理前两个回调函数的错误
});
Promise.all方法
var p = Promise.all([p1,p2,p3]);
这个方法接受一个数组作为参数,p1,p2,p3都是Promise对象的实例。p的最终状态取决于参数对象数组的状态,上例中就是p1,p2,p3来决定的。如果这三个都是fulfilled,那么p的状态就是fulfilled;如果p1,p2,p3中有一个是rejected,p的状态就是rejected.那么p的状态就是reject,会传递给p的回调函数。
// 生成一个Promise对象的数组
var promises = [2, 3, 5, 7, 11, 13].map(function(id){
return getJSON("/post/" + id + ".json");
});
Promise.all(promises).then(function(posts) {
// ...
}).catch(function(reason){
// ...
});
Promise.resolve方法,Promise.reject方法
将现有对象转我Promise对象,Promise.resolve方法就起到这个作用。
var jsPromise = Promise.resolve($.ajax('/whatever.json'));
上面jQuery生成defferred对象,转为一个新的ES6的Promise对象。
如果Promise.resolve方法的参数,不具有then方法的对象(又称thenable对象),则返回一个新的Promise对象,且他的状态为fulfilled.
var p = Promise.resolve('Hello');
p.then(function(s){
console.log(s)
})
//Hello
上面生成一个新的Promise对象的实例p,它的状态为fulfilled。
Promise.reject(reason)方法也会返回一个新的Promise实例,该实例的状态为rejected,Promise.reject方法的参数reason,会被传递给实例的回调函数。
async函数
async函数是用来取代回调函数的另一种方法。只要函数之前加上async的关键字,就表明该函数内部有异步操作。该异步操作返回一个Promise对象,前面用await关键字注明。当函数执行的时候,一旦遇到await就立马返回,等接触到异步操作完成,再接着执行函数体内后面的语句。
async function getStockPrice(symbol, currency) {
let price = await getStockPrice(symbol);
return convert(price, currency);
}
函数前面加了一个async表明该函数将返回一个Promise对象,调用该函数时,遇到await关键字,立刻返回后面的表达式产生的Promise对象,不再执行函数体后面的语句。等getStockPrice完成,在自动回到函数体内,执行剩下的语句。
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}
async function asyncValue(value) {
await timeout(50);
return value;
}
上面代码中,asyncValue函数前面有async关键字,表明函数体内有异步操作。执行的时候,遇到await语句就会先返回,等到timeout函数执行完毕,再返回value。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。