本篇博文出至於個人
github
倉庫:web-study,若是你以爲對你有幫助歡迎star,大家的點贊是我持續更新的動力,謝謝!javascript
異步編程在前端開發中尤其常見,從最先的XHR
,到後來的各類封裝ajax
,再到DOM
事件觸發的回調,無不涉及異步編程。今天我們來聊聊ES6
中新提出的異步解決方案:Promise
和async/await
。前端
Promise 是一種對異步操做的封裝,能夠經過獨立的接口添加在異步操做執行成功、失敗時執行的方法。主流的規範是 Promises/A+。java
Promise中有幾個狀態:node
* pending: 初始狀態, 非 fulfilled 或 rejected; * fulfilled: 成功的操做,爲表述方便,fulfilled 使用 resolved 代替; * rejected: 失敗的操做。
pending能夠轉化爲fulfilled或rejected而且只能轉化一次,也就是說若是pending轉化到fulfilled狀態,那麼就不能再轉化到rejected。而且fulfilled和rejected狀態只能由pending轉化而來,二者之間不能互相轉換。git
Promise是一個構造函數,本身身上有all、reject、resolve這幾個眼熟的方法,原型上有then、catch等一樣很眼熟的方法。github
resolve
的用法web
var p = new Promise(function(resolve, reject){ //作一些異步操做 setTimeout(function(){ resolve('隨便什麼數據'); }, 2000); }) p.then(res => { console.log(res) // '隨便什麼數據' })
Promise的構造函數接收一個參數,是函數,而且傳入兩個參數:resolve,reject,分別表示異步操做執行成功後的回調函數和異步操做執行失敗後的回調函數。其實這裏用「成功」和「失敗」來描述並不許確,按照標準來說,resolve是將Promise的狀態置爲fullfiled,reject是將Promise的狀態置爲rejected。ajax
在上面的代碼中,咱們執行了一個異步操做,也就是setTimeout
,2秒後,而且調用resolve方法,表示異步操做執行成功。編程
reject
的用法javascript var p = new Promise(function(resolve, reject){ //作一些異步操做 setTimeout(function(){ reject('隨便什麼數據'); }, 2000); }) p.catch(err => { console.log(err) // '隨便什麼數據' })
promise
上面咱們在異步操做中調用了reject
方法,也就是說把Promise的狀態由pending
轉換到了fulfilled
狀態,最後能夠經過Promise實例對象的catch()
方法獲取異步數據。
異步操做是 JavaScript 編程的麻煩事,不少人認爲async函數是異步操做的終極解決方案。
async/await是寫異步代碼的新方式,優於回調函數和Promise。
async/await是基於Promise實現的,它不能用於普通的回調函數。
async/await與Promise同樣,是非阻塞的。
async/await使得異步代碼看起來像同步代碼,再也沒有回調函數。可是改變不了JS單線程、異步的本質。
使用await,函數必須用async標識
await後面跟的是一個Promise實例或者是其餘的任意js表達式(意義不大)
var fun = async () => { let result = await Promise.resolve(123) console.log(result) } fun() // 123
await
等待的雖然是promise對象,可是不用調用.then()方法就能直接獲得返回值。
Promise
雖然一方面解決了callback
的回調地獄,可是相對的把回調「縱向發展」了,造成了一個回調鏈。example:
function sleep(wait) { return new Promise((res,rej) => { setTimeout(() => { res(wait) },wait) }) } /* let p1 = sleep(100) let p2 = sleep(200) let p =*/ sleep(100).then(result => { return sleep(result + 100) }).then(result02 => { return sleep(result02 + 100) }).then(result03 => { console.log(result03) })
控制檯輸出:
300
後面的結果都是依賴前面的結果。
改爲async/await寫法就是:
async function demo() { let result01 = await sleep(100) //上一個await執行以後纔會執行下一句 let result02 = await sleep(result01 + 100) let result03 = await sleep(result02 + 100) // console.log(result03); return result03 } demo().then(result => { console.log(result) })
由於async返回的也是promise對象,因此用then接受就好了。
結果:
300
須要注意的就是 await
是強制把異步變成了同步,這一句代碼執行完,纔會執行下一句。