前言 本篇博文出至於我的 倉庫: "web study" ,如果你覺得對你有幫助歡迎star,你們的點贊是我持續更新的動力,謝謝! 非同步編程在前端開發中尤為常見,從最早的 ,到後來的各種封裝 ,再到 事件觸發的回調,無不涉及非同步編程。今天咱們來聊聊 中新提出的非同步解決方案: 和`async/awai ...
前言
本篇博文出至於我的
github
倉庫:web-study,如果你覺得對你有幫助歡迎star,你們的點贊是我持續更新的動力,謝謝!
非同步編程在前端開發中尤為常見,從最早的XHR
,到後來的各種封裝ajax
,再到DOM
事件觸發的回調,無不涉及非同步編程。今天咱們來聊聊ES6
中新提出的非同步解決方案:Promise
和async/await
。
- Promise的原理和基本用法
- Promise的原理
Promise 是一種對非同步操作的封裝,可以通過獨立的介面添加在非同步操作執行成功、失敗時執行的方法。主流的規範是 Promises/A+。
Promise中有幾個狀態:
* pending: 初始狀態, 非 fulfilled 或 rejected;
* fulfilled: 成功的操作,為表述方便,fulfilled 使用 resolved 代替;
* rejected: 失敗的操作。
pending可以轉化為fulfilled或rejected並且只能轉化一次,也就是說如果pending轉化到fulfilled狀態,那麼就不能再轉化到rejected。並且fulfilled和rejected狀態只能由pending轉化而來,兩者之間不能互相轉換。
- Promise的基本用法
Promise是一個構造函數,自己身上有all、reject、resolve這幾個眼熟的方法,原型上有then、catch等同樣很眼熟的方法。
resolve
的用法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。
在上面的代碼中,我們執行了一個非同步操作,也就是setTimeout
,2秒後,並且調用resolve方法,表示非同步操作執行成功。
reject
的用法
javascript var p = new Promise(function(resolve, reject){ //做一些非同步操作 setTimeout(function(){ reject('隨便什麼數據'); }, 2000); }) p.catch(err => { console.log(err) // '隨便什麼數據' })
上面我們在非同步操作中調用了reject
方法,也就是說把Promise的狀態由pending
轉換到了fulfilled
狀態,最後可以通過Promise實例對象的catch()
方法獲取非同步數據。
- Async/Await簡介與用法
非同步操作是 JavaScript 編程的麻煩事,很多人認為async函數是非同步操作的終極解決方案。
- Async/Await簡介
async/await是寫非同步代碼的新方式,優於回調函數和Promise。
async/await是基於Promise實現的,它不能用於普通的回調函數。
async/await與Promise一樣,是非阻塞的。
async/await使得非同步代碼看起來像同步代碼,再也沒有回調函數。但是改變不了JS單線程、非同步的本質。
- Async/Await的用法
使用await,函數必須用async標識
await後面跟的是一個Promise實例或者是其他的任意js表達式(意義不大)
var fun = async () => {
let result = await Promise.resolve(123)
console.log(result)
}
fun() // 123
await
等待的雖然是promise對象,但是不用調用.then()方法就能直接得到返回值。
- Async/Await的應用
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
是強制把非同步變成了同步,這一句代碼執行完,才會執行下一句。