本系列屬於阮一峯老師所著的ECMAScript 6 入門學習筆記javascript
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) })
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
方式是.then(null,rejection)
的別名,用於指定發生錯誤時的回調函數
getJSON('/posts.json').then(post=>{ ... }).catch(error =>{ // 處理getJSON和前一個回調函數運行時發生的錯誤 console.log('發生錯誤',error) }) // Promise內部的錯誤不會影響Promise外部的代碼
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實例,包裝成一個新的Promise實例
// 只要三個實例中有一個實例率先改變狀態,p就會隨着改變,率先改變的Promise實例的返回值就傳遞給p的回調函數 var p = Promise.race([p1,p2,p3])
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
方法返回一個狀態爲rejected
的新的Promise實例
//生成一個狀態爲rejected的實例 var p = Promise.reject('出錯了') p.then(null,function(s){ console.log(s) // 出錯了 }) //與Promise.resove方法不一樣的是Promise.reject方法的參數會原封不動的變爲後續方法的參數
//由於Promise內部的錯誤不會冒泡到全局,done能夠保證拋出任何可能出現的錯誤 asyncFunc().then(f1).catch(f2).then(f3).done()
finally
用於指定無論Promse對象最後的狀態如何,都會執行的操做。與done
最大的不一樣是接收一個普通的回調函數做爲參數,該函數無論怎樣都會執行
server.listen(0).then(()=>{}).finally(server.stop)