一看就懂的async-await
- async-await異步處理和使用
- async-await基本使用
- async
- await
- 回調執行個體
- 小心并行處理
async-await異步處理和使用
好不容易看完了
Promise
心想着可算是能用一下了,結果就看到了各種标題為:有了
async-await以後promise還有必要學習嗎?
、
async await優于promise的幾個特點
。。。然後我就懵圈了,我的内心emmmmm。
原來,
async-await
是
promise
和
generator
的文法糖,隻是為了讓我們書寫代碼更加流暢,增強代碼的可讀性,簡而言之:
async-await
是建立在
promise
機制之上的,并不能取代
promise
。
async-await基本使用
async
函數傳回一個
Promise
對象,可以使用
then
方法添加回調函數。
當函數執行的時候,一旦遇到
await
就會先傳回,等到異步操作完成,再接着執行函數體内後面的語句。
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
async function asyncPrint(value, ms) {
await timeout(ms)
console.log(value)
}
asyncPrint('hello world', 2000);
//hello world (2s後)
上面代碼指定2000毫秒以後,輸出
hello world
。同時函數
asyncPrint()
執行結果傳回了一個
promise
對象。
async
async
用來表示函數是異步的,定義的函數會傳回一個
promise
對象,可以使用
then
方法添加回調函數,而
async
函數内部
return
語句傳回的值,就會成為
then
方法回調函數的參數。針對上面的
asyncPrint
例子來看,如果我們直接使用
then
會發現什麼都沒有
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
async function asyncPrint(value, ms) {
await timeout(ms)
console.log(value)
}
asyncPrint('hello world', 2000).then((value)=>{console.log(value)})
//hello world (2s後)
//undefined
因為函數
asyncPrint
内部沒有
return
語句傳回值,那我們加上
return
試一下
function timeout(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms)
})
}
async function asyncPrint(value, ms) {
await timeout(ms)
console.log(value)
return 'done'
}
asyncPrint('hello world', 2000).then((value)=>{console.log(value)})
//hello world (2s後)
//done
其實就是相當于執行了
Promise.resolve('done')
,如果沒有
return
就相當于
Promise.resolve()
。
await
await
後面可以跟任何JS表達式,雖然
await
可以跟很多類型的東西,但是最主要的意圖是用來等待
Promise
對象的狀态被
resolved
,如果
await
的是
promise
對象會造成異步函數停止執行并等待
promise
解決,如果等到的是正常的表達式就立即執行,還是開頭的那個例子,如果
await
的不是
promise
對象會怎麼樣
function timeout(ms) {
setTimeout(()=>{}, ms)
}
async function asyncPrint(value, ms) {
await timeout(ms)
console.log(value)
}
asyncPrint('hello world', 2000);
//hello world (立即)
因為
await
後面不是promise對象了,也就不需要等待結果傳回了,是以到這就直接往下執行了。
再來一個例子
function sleep(second) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('enough sleep~');
}, second);
})
}
function normalFunc() {
console.log('normalFunc');
}
async function awaitDemo() {
await normalFunc();
console.log('something, ~~');
let result = await sleep(2000);
console.log(result);// 兩秒之後會被列印出來
}
awaitDemo();
// normalFunc
// something, ~~
// ---2s後---
// enough sleep~
第一個
await
後面是一個正常表達式是以直接執行後繼續往下執行,然後再遇到第二個
await
,這個
await
後面是一個異步操作,是以需要等待結果傳回并執行後再繼續往下執行,也就是過了2s以後再列印最後的值。
回調執行個體
舉例說明,假設有三個請求需要發生,第三個請求是依賴第二個請求的解析,第二個請求是依賴第一個請求的解析
如果要用ES5實作就會有三個回調
如果用Promise就會至少有三個then
一個是橫向代碼很長,一個是縱向代碼很長,如果用
async-await
來實作呢?
//我們仍然使用 setTimeout 來模拟異步請求
function sleep(second, param) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(param);
}, second);
})
}
async function test() {
let result1 = await sleep(1000, 'req01');
console.log(result1)
let result2 = await sleep(1000, 'req02' + result1);
console.log(result2)
let result3 = await sleep(1000, 'req03' + result2);
console.log(result3)
}
test();
//req01 --1s後--
//req02req01 --2s後--
//req03req02req01 --3s後--
難怪說
async-await
是
promise
的文法糖了,其實還是
promise
,隻是代碼閱讀起來讓你覺得它好像是一個同步請求,不用那麼多回調或者
then
了。amazing!!!
小心并行處理
如果有多個await指令後面的異步操作之間不存在互相依賴的關系,那我們當然就不能使用上面執行個體中的方法來使用async-await了
例如有三個異步請求需要發送,但是互相之間沒有關聯,要做的其實就是當所有異步請求結束後清除界面上的loading,如果我們像上面那樣使用當最後一個請求結束後清除loading,其實等待的時間就是三個請求時間之和:
function sleep(second) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('sth');
}, second);
})
}
async function clearLoad() {
await sleep(1000);
await sleep(1000);
await sleep(1000);
console.log('清除loading啦');
}
clearLoad();
// 清除loading啦 --3s後--
其實這裡真正的需求是當最慢的那個請求發送結束了,就可以清除loading了,是以改良後是這樣:
function sleep(second) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve('sth');
}, second);
})
}
async function clearLoad() {
let p1 = sleep(1000);
let p2 = sleep(1000);
let p3 = sleep(1000);
await Promise.all([p1, p2, p3]);
console.log('清除loading啦');
}
clearLoad();
// 清除loading啦 --1s後--
是以,以上可以得出:
async-await
是
promise
的文法糖,讓我們書寫代碼更加流暢,增強代碼的可讀性,它是建立在
promise
機制之上的,并不能取代
promise
。