https://www.jianshu.com/p/c98eb98bd00cjavascript
相信凡是寫過javascript的童鞋也必定都寫過回調方法(callback),簡單說回調方法就是將一個方法func2做爲參數傳入另外一個方法func1中,當func1執行到某一步或者知足某種條件的時候才執行傳入的參數func2,例以下面的代碼段html
// 當參數a大於10且參數func2是一個方法時 執行func2 function func1(a, func2) { if (a > 10 && typeof func2 == 'function') { func2() } } func1(11, function() { console.log('this is a callback') })
通常來講咱們會碰到的回調嵌套都不會不少,通常就一到兩級,可是某些狀況下,回調嵌套不少時,代碼就會很是繁瑣,會給咱們的編程帶來不少的麻煩,這種狀況俗稱——回調地獄。極端狀況以下圖:java
由此,Promise的概念就由社區提出並實現,做用與回調方法幾乎一致,都是在某種狀況下執行預先設定好的方法,可是使用它卻可以讓代碼變得更簡潔清晰編程
Promise是異步編程的一種解決方案,它有三種狀態,分別是pending-進行中、resolved-已完成、rejected-已失敗api
當Promise的狀態又pending轉變爲resolved或rejected時,會執行相應的方法,而且狀態一旦改變,就沒法再次改變狀態,這也是它名字promise-承諾的由來數組
在ES6中,Promise終於成爲了原生對象,能夠直接使用。可是在這以前,小夥伴們想要使用Promise,通常會藉助於第三方庫,或者當你知道其中的原理之後,也能夠手動實現一個簡易的Promisepromise
固然,爲了防止不可預知的bug,在生產項目中最好仍是不要使用原生的或者本身編寫的Promise(目前爲止並非全部瀏覽器都能很好的兼容ES6),而是使用已經較爲成熟的有大量小夥伴使用的第三方Promise庫,下面就爲小夥伴推薦一個—— Bluebird瀏覽器
// 方法1 let promise = new Promise ( (resolve, reject) => { if ( success ) { resolve(a) // pending ——> resolved 參數將傳遞給對應的回調方法 } else { reject(err) // pending ——> rejectd } } ) // 方法2 function promise () { return new Promise ( function (resolve, reject) { if ( success ) { resolve(a) } else { reject(err) } } ) }
注意:實例化的Promise對象會當即執行異步
.then()方法使Promise原型鏈上的方法,它包含兩個參數方法,分別是已成功resolved的回調和已失敗rejected的回調異步編程
promise.then(
() => { console.log('this is success callback') }, () => { console.log('this is fail callback') } )
.catch()的做用是捕獲Promise的錯誤,與then()的rejected回調做用幾乎一致。可是因爲Promise的拋錯具備冒泡性質,可以不斷傳遞,這樣就可以在下一個catch()中統一處理這些錯誤。同時catch()也可以捕獲then()中拋出的錯誤,因此建議不要使用then()的rejected回調,而是統一使用catch()來處理錯誤
promise.then(
() => { console.log('this is success callback') } ).catch( (err) => { console.log(err) } )
一樣,catch()中也能夠拋出錯誤,因爲拋出的錯誤會在下一個catch中被捕獲處理,所以能夠再添加catch()
使用rejects()方法改變狀態和拋出錯誤 throw new Error() 的做用是相同的
當狀態已經改變爲resolved後,即便拋出錯誤,也不會觸發then()的錯誤回調或者catch()方法
then() 和 catch() 都會返回一個新的Promise對象,能夠鏈式調用
promise.then(
() => { console.log('this is success callback') } ).catch( (err) => { console.log(err) } ).then( ... ).catch( ... )
// p1異步方法中返回p2 let p1 = new Promise ( (resolve, reject) => { resolve(p2) } ) let p2 = new Promise ( ... ) // then()中返回promise let p3 = new Promise ( (resolve, reject) => { resolve() } ) let p4 = new Promise ( ... ) p3.then( () => return p4 )
p1異步方法中返回p2
p1的狀態取決於p2,若是p2爲pending,p1將等待p2狀態的改變,p2的狀態一旦改變,p1將會當即執行本身對應的回調,即then()中的方法針對的依然是p1
then()中返回promise
因爲then()自己就會返回一個新的promise,因此後一個then()針對的永遠是一個新的promise,可是像上面代碼中咱們本身手動返回p4,那麼咱們就能夠在返回的promise中再次經過 resolve() 和 reject() 來改變狀態
用來包裝一個現有對象,將其轉變爲Promise對象,但Promise.resolve()會根據參數狀況返回不一樣的Promise:
參數是Promise:原樣返回
參數帶有then方法:轉換爲Promise後當即執行then方法
參數不帶then方法、不是對象或沒有參數:返回resolved狀態的Promise
Promise.reject()會直接返回rejected狀態的Promise
參數爲Promise對象數組,若是有不是Promise的對象,將會先經過上面的Promise.resolve()方法轉換
var promise = Promise.all( [p1, p2, p3] ) promise.then( ... ).catch( ... )
當p一、p二、p3的狀態都變成resolved時,promise纔會變成resolved,並調用then()的已完成回調,但只要有一個變成rejected狀態,promise就會馬上變成rejected狀態
var promise = Promise.race( [p1, p2, p3] ) promise.then( ... ).catch( ... )
「競速」方法,參數與Promise.all()相同,不一樣的是,參數中的p一、p二、p3只要有一個改變狀態,promise就會馬上變成相同的狀態並執行對於的回調
Promise.done() 的用法相似 .then() ,能夠提供resolved和rejected方法,也能夠不提供任何參數,它的主要做用是在回調鏈的尾端捕捉前面沒有被 .catch() 捕捉到的錯誤
Promise. finally() 接受一個方法做爲參數,這個方法無論promise最終的狀態是怎樣,都必定會被執行