Promise对象
本系列属于阮一峰老师所著的ECMAScript 6 入门学习笔记
Promise的含义
Promise是异步编程的一种解决方案。
所谓Promise,简单说是一个容器,里面保存这某个未来才会结束的事件的结果。
Promise对象有以下两个特点:
1.对象的状态不受外部影响。Promise对象代表一个异步操作,有三种状态:pending (进行中)、fulfilled (已成功)和rejected (已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。
2.一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。只要这两种情况发生了,状态就凝固了,会一直保持这个结果,这时称为rejected(已定型)。
基本用法
var promise = new Promise(function(resolve,reject){
// ... some code
if(/*异步操作成功*/){
resolve(value)
}else{
reject(error)
}
})
resolve函数的作用是将Promise对象的状态从pending变成resolved,并将异步操作的结果作为参数传递出去。
reject函数的作用是将Promise对象的状态从pending变成rejected,在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
Promise实例生成后,可以用then方法分别指定resolved状态和rejected状态的回调函数
function timeout(ms){
return new Promise((resolve,reject)=>{
setTimeout(reslove,ms,'done')
})
}
// Promise新建后就会立即执行
timeout(100).then(value=>{
console.log(value)
})
Promise.prototype.then()
then的作用是为Promise实例添加状态改变时的回调函数,then的第一个参数是resolved状态的回调函数,第二个参数(可选)是rejected状态的回调函数。
then方法返回的是一个新的Promise实例(注意,不是原来的那个Promise实例),因此可以采用链式写法
getJson('/posts.json').then(function(json){
return json.post
}).then(function(post){
...
})
// 使用then的第一个回调函数如果还是一个Promise对象,后一个回调函数,会等待Promise对象的状态发生改变才会被调用
getJson('/post/1.json').then(
post=>getJson(post.commentURL)
).then(
comments => console.log('resolved:',comments),
err => console.log('rejected',err)
)
Promise.prototype.catch()
Promise.prototype.catch方式是.then(null,rejection)的别名,用于指定发生错误时的回调函数
getJSON('/posts.json').then(post=>{
...
}).catch(error =>{
// 处理getJSON和前一个回调函数运行时发生的错误
console.log('发生错误',error)
})
// Promise内部的错误不会影响Promise外部的代码
Promise.all()
Promise.all方法用于将多个Promise实例,包装成一个新的Promise实例
// 只有p1、p2、p3的状态都变为fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数
//只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个rejected实例的返回值会传递给p的回调函数
var p = Promise.all([p1,p2,p3])
//生成一个Promise对象的数组
var promises = [2,3,4,5,6,7,8].map(id=>{
return getJSON('/post'+id+'.json')
})
Promise.all(promises).then(posts=>{
// ...
}).catch(error=>{
// ...
})
// 只有所有实例状态变为fulfilled或者其中一个变为rejected才会调用Promise.all方法后面的回调函数
// 如果作为参数的Promise实例自己定义了catch方法,那么它一旦被rejected,就不会触发Promise.all()的catch方法
Promise.race()
Promise.race()方法同样是将多个Promise实例,包装成一个新的Promise实例
// 只要三个实例中有一个实例率先改变状态,p就会随着改变,率先改变的Promise实例的返回值就传递给p的回调函数
var p = Promise.race([p1,p2,p3])
Promise.resolve()
Promise.resolve方法可以将现有对象转化为Promise对象
Promise.resolve('foo')
// 等价于
new Promise(resolve=>resolve('foo'))
Promise.resolve方法的参数分为四种情况
1.参数是一个Promise实例
Promise.resolve不做任何修改、原封不动返回Promise实例
2.参数是一个thenable对象
thenable对象指的是具有then方法的对象
let thenable = {
then: function(resolve,reject){
resolve(40)
}
}
let p1 = Promise.resolve(thenable)
p1.then(function(value){
console.log(value) // 42
})
3.参数不是具有then方法的对象,或根本就不是对象
var p = Promise.resolve('Hello')
// 字符串不属于异步操作(判断方法是字符串对象不具有then方法),返回Promise一生成就是resolved,回调函数会立即执行,Promise.resove方法的参数会同时传给回调函数
p.then(function(s){
console.log(s) // Hello
})
4.不带任何参数
var p = Promise.resolve()
p.then(function(){
// ...
})
setTimeout(function(){
console.log('three')
},0)
// 在下一轮事件循环开始时立即执行
Promise.resolve().then(function(){
console.log('two')
})
//在本轮事件循环结束时执行
console.log('one')
//立即执行
Promise.reject()
promise.reject方法返回一个状态为rejected的新的Promise实例
//生成一个状态为rejected的实例
var p = Promise.reject('出错了')
p.then(null,function(s){
console.log(s) // 出错了
})
//与Promise.resove方法不同的是Promise.reject方法的参数会原封不动的变为后续方法的参数
done()
//因为Promise内部的错误不会冒泡到全局,done可以保证抛出任何可能出现的错误
asyncFunc().then(f1).catch(f2).then(f3).done()
finally()
finally用于指定不管Promse对象最后的状态如何,都会执行的操作。与done最大的不同是接收一个普通的回调函数作为参数,该函数不管怎样都会执行
server.listen(0).then(()=>{}).finally(server.stop)

浙公网安备 33010602011771号