在咱們使用異步函數好比ajax進行編寫代碼,若是咱們須要不少個ajax請求不一樣的接口,而下一個接口須要依賴上一個接口的返回值,這樣,咱們的代碼則須要在各類回調函數中嵌套,這樣一層一層地下去,就造成了回調地獄。
可是promise的出現則不須要嵌套就能解決這個問題。什麼是promise?promise本質實際上是一個對象,用於傳遞異步操做的信息。而且promise這個對象提供了相對應的API,知足咱們的需求開發。ajax
let pro = new Promise(function(resolve, reject){ // 異步處理邏輯 // 處理完畢以後調用resolve或者reject })
promise對象跟其餘普通對象的建立方法同樣,只須要new一個新的對象便可,接受一個函數做爲參數,而且該函數中的參數分別爲兩個回調函數,用於進行不一樣的邏輯處理。
在定完一個promise對象以後,咱們能夠經過調用then方法來執行其對應的邏輯數組
pro.then(function(res){ // 若是promise對象調用了resolve方法,則進入該函數邏輯 }, function(err){ // 若是promise對象調用了reject方法,則進入該函數邏輯 })
promise的實例主要有如下三種狀態:
①pending: 處理中
②fulfilled: 成功
③rejected: 失敗promise
pending狀態的promise能夠轉化爲fulfilled狀態或者rejected狀態,該轉化不可逆且只能轉化一次。同時,fulfilled狀態和rejected狀態只能由pending狀態轉化,相互不能轉化。如圖異步
pending狀態下的promise在處理完業務邏輯,且能正常退出時即可以執行resolve方法,從而進入fulfilled狀態;
若pending狀態下的promise在處理業務邏輯的過程當中出現異常錯誤,或者主動調用reject方法,則進入rejected狀態。async
let pro = new Promise(function(resolve, reject){ if(// 邏輯處理完畢且能正常退出){ resolve() } else{ // 異常錯誤拋出 reject() } }) pro.then(function(res){ // 若是promise對象調用了resolve方法,則進入該函數邏輯 }, function(err){ // 若是promise對象調用了reject方法,則進入該函數邏輯 })
由於promise對象中的then方法的返回值是一個新的promise對象,所以能夠實現鏈式調用。但後一個then方法的執行必須等待前一個then方法返回的promise對象狀態轉爲fulfilled或者rejected,若promise對象處於pending狀態下,則後一個then方法只能等待。函數
pro.then(function(res){ // 第一個promise對象邏輯執行 return newPro;// 返回一個新promise }).then(function(res){ // 對newPro這個對象進行處理 }) // ...能夠一直鏈式調用下去
promise中的catch方法其實就是pro.then(null, rejection),用戶捕捉代碼運行中的錯誤異常。優化
pro.then(function(res){ // 邏輯處理,但存在異常 }).catch(function(err){ // 捕捉上一個then函數中所出現的異常錯誤 })
此外,catch方法的所捕捉的異常不只僅侷限於上一個then方法內,而是能夠把錯誤一直傳遞下來,直至遇到的第一個catch,而後被捕捉。如鏈式調用中:spa
pro.then(function(res){ // 邏輯處理,但存在異常 }).then({ // 邏輯處理 }).catch(function(err){ // 捕捉上面第一個出現異常的then函數中所出現的錯誤 })
promise.all方法能夠接受一個由promise組成的數組做爲參數,包裝成一個新的promise對象,而且按照數組中promise的順序進行異步執行。如:code
let pro1 = new Promise(function(resolve, reject){}); let pro2 = new Promise(function(resolve, reject){}); let pro3 = new Promise(function(resolve, reject){}); let proAll = promise.all([pro1, pro2, pro3]);
proAll的狀態由pro1,pro2,pro3三者共同決定:
①pending: 處理中,pro1,pro2,pro3中無rejected且存在pending狀態。
②rejected: pro1,pro2,pro3中存在一個rejected。
③fulfilled:pro1,pro2,pro3三者均爲fulfilled。對象
當proAll的狀態爲fulfilled時,會返回一個數組,該數組中的元素則是上面由promise組成的數組相對應執行後的結果。
promise.race所接受的參數與promise.all一致,但promise.race的返回值則是由pro1,pro2,pro3三者中最早完成的promise對象決定,而且返回值爲該最先完成的promise對象的返回值。
let proAll = promise.race([pro1, pro2, pro3]);
promise.resolve方法能將一個對象轉換成promise對象
let newPro = promise.resolve(obj);
①若obj不具備then方法,則newPro直接變爲fulfilled狀態
let newPro = promise.resolve('i am not a promise'); newPro.then(function(str){ console.log(str) // 輸出 i am not a promise })
②若是obj本就是一個Promise對象,則promise.resolve會將obj直接返回。
promise.reject方法與promise.resolve同樣,能將一個對象轉換成promise對象,但返回的promise對象的狀態爲rejected。
async是關鍵詞,在一個函數名以前加上該關鍵詞,代表該函數內部有異步操做,而這異步操做應該返回一個promise對象,而且在這異步操做以前添加await關鍵詞。當函數執行的時候,遇到await則會先進行Promise的邏輯處理,帶promise的狀態再也不爲pending時再執行該函數後面的語句。
let pro = new Promise(function(resolve, reject){ // 異步處理邏輯 resolve(); }) async function asyncFunc(){ // 正常執行的語句 await pro; // 等待promise處理完以後再執行的語句 } asyncFunc();
promise的出現,爲咱們編寫異步函數定下很多規則,在優化咱們代碼的同時也能減小代碼量,並加強可讀性,但也需嚴格遵照promise/A+的規範進行promise的開發。