javascript中async/await常用場(chǎng)景
我們開發(fā)過程中,經(jīng)常會(huì)使用到Promise,它很好的解決了異步問題。但是,在業(yè)務(wù)邏輯比較復(fù)雜的情況下,單純的使用Promise并不好用。這時(shí),我們可以使用ES7中新添加的async/await,在async標(biāo)記的函數(shù)中,如果遇到await表達(dá)式,則函數(shù)會(huì)等待await標(biāo)記的Promise解析完成,然后才會(huì)繼續(xù)執(zhí)行下面的代碼。
那么,我們來舉幾個(gè)例子看看什么時(shí)候比較適合使用async/await:
假設(shè)我們有如下兩個(gè)方法:
function convertToBase64Data(url) { // 轉(zhuǎn)成base64格式
return new Promise( resolve => {
setTimeout( () => {
resolve('img');
}, 1000);
});
}
function saveToLocal(img) { // 保存到本地
return new Promise( resolve=> {
setTimeout( () => {
resolve('success');
}, 200);
});
}
場(chǎng)景1:多個(gè)異步需要按順序:圖片處理完成然后保存在本地
用promise我們可能這樣寫:
function fn1() {
return convertToBase64Data('http://1.jpg').then( base64Data => {
return saveToLocal(base64Data);
})
}
使用await則更簡(jiǎn)潔,更好理解:
async function fn1() {
const base64Data = await download('http://1.jpg');
const result = await saveToLocal(base64Data);
return result;
}
場(chǎng)景2:圖片需要同時(shí)處理,但是要按順序一張一張保存在本地
不使用await:
function fn2() {
const promise1 = convertToBase64Data('http://1.jpg');
const promise2 = convertToBase64Data('http://1.jpg');
Promise.all([promise1,promise2]).then( datas => {
saveToLocal(datas[0]).then( result1 => {
saveToLocal(datas[1]).then(result2 => {
console.log(result2);
})
})
})
}
我們看到,回調(diào)很多,很不方便,下面是使用await:
async function fn2() {
// 同時(shí)處理兩張
const promise1 = convertToBase64Data('http://1.jpg');
const promise2 = convertToBase64Data('http://2.jpg');
const [data1, data2] = await Promise.all([promise1, promise2]);
// 先保存第一張
const result = await saveToLocal(data1);
// 再保存第二張
const result2 = await saveToLocal(data2);
}
代碼層次很清晰,很容易閱讀。
場(chǎng)景3:多張圖片,處理一張保存一張,然后才能處理下一張
不使用await:
// 你來寫寫看?。?!
使用await:
async function fn3() {
const imgUrls = ['http://1.jpg', 'http://2.jpg', 'http://3.jpg', 'http://4.jpg', 'http://5.jpg'];
for (let i = 0; i < imgUrls.length; i++) {
const base64Data = await convertToBase64Data(imgUrls[i]);
const result = await saveToLocal(base64Data);
console.log(result);
}
}
是不是覺得很爽?
場(chǎng)景4:條件語(yǔ)句
不使用await:
function fn4(needConvertToBase64) {
return download('http://1.jpg').then( img => {
if (needConvertToBase64) {
return convertToBase64(img).then(base64Data => {
return base64Data;
});
} else {
return img;
}
});
}
return 到讓人迷茫。下面使用await, 這就很爽:
async function fn4(needConvertToBase64) {
const img = await download('http://1.jpg');
if (needConvertToBase64) {
const base64Data = await convertToBase64(img);
return base64Data;
}
return img;
}
場(chǎng)景5: 你可能會(huì)這樣:調(diào)用方法1,使用方法1返回的結(jié)果去調(diào)用方法2,然后使用兩者的結(jié)果去調(diào)用方法3。
假設(shè)有如下業(yè)務(wù): 獲取用戶ID,然后根據(jù)ID獲取用戶信息,然后將兩者保存在服務(wù)器。
function getUserId() {
return Promise.resolve('123123');
}
function getUserInfo(id) {
return Promise.resolve({name: 'aaron'});
}
function saveToServer(id, userInfo) {
return Promise.resolve('success');
}
你的代碼很可能是這樣的:
function fn5() {
return getUserId().then( id => { // 拿到id
return getUserInfo(id).then( userInfo => {
return saveToServer(id, userInfo);
});
});
}
使用await:
async function fn5() {// 使用await
const id = await getUserId();
const userInfo = await getUserInfo(id);
return saveToServer(id, userInfo);
}
場(chǎng)景6:錯(cuò)誤處理
不使用await,try/catch不能捕獲saveToLocal的錯(cuò)誤,convertToBase64 的Promise中,只能.catch處理,這樣錯(cuò)誤處理代碼非常冗余,使代碼很復(fù)雜:
function fn6() {
try {
convertToBase64('http://1.jpg').then( data => {
// saveToLocal可能會(huì)出錯(cuò)
saveToLocal(data).then( result => {
console.log(result);
});
// .catch(err => { console.log(err)}); // 只能在.catch中處理
});
} catch (err) { // 這里取不到saveToLocal的錯(cuò)誤
console.log(err);
}
}
使用await,try/catch能捕獲saveToLocal的錯(cuò)誤:
async function fn6() {
try {
const data = await convertToBase64('http://1.jpg');
const result = await saveToLocal(data);
console.log(result);
} catch (err) {
console.log(err);
}
}