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)
posted @ 2017-10-16 21:36  coderAngus  阅读(152)  评论(0)    收藏  举报