Promise對象

本系列屬於阮一峯老師所著的ECMAScript 6 入門學習筆記javascript


Promise的含義

Promise是異步編程的一種解決方案。java

所謂Promise,簡單說是一個容器,裏面保存這某個將來纔會結束的事件的結果。es6

Promise對象有如下兩個特色:編程

1.對象的狀態不受外部影響。Promise對象表明一個異步操做,有三種狀態:pending (進行中)、fulfilled (已成功)和rejected (已失敗)。只有異步操做的結果,能夠決定當前是哪種狀態,任何其餘操做都沒法改變這個狀態。json

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,並將異步操做的結果做爲參數傳遞出去。promise

reject函數的做用是將Promise對象的狀態從pending變成rejected,在異步操做失敗時調用,並將異步操做報出的錯誤,做爲參數傳遞出去。異步

Promise實例生成後,能夠用then方法分別指定resolved狀態和rejected狀態的回調函數async

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實例

// 只有p一、p二、p3的狀態都變爲fulfilled,p的狀態纔會變成fulfilled,此時p一、p二、p3的返回值組成一個數組,傳遞給p的回調函數
//只要p一、p二、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)
相關文章
相關標籤/搜索