作用
async
和await
是用來處理異步的纹安。即你需要異步像同步一樣執(zhí)行陆淀,需要異步返回結(jié)果之后考余,再往下依據(jù)結(jié)果繼續(xù)執(zhí)行。
async
是“異步”的簡寫轧苫,而 await
可以認為是 async wait
的簡寫楚堤。
async
用于申明一個 function
是異步的,而 await
用于等待一個異步方法執(zhí)行完成含懊。
async
async function testAsync() {
return "hello async";
}
const result = testAsync();
console.log(result);
打印輸出的是一個Promise
對象身冬,async
函數(shù)會返回一個 Promise
對象。
在最外層不能用 await
獲取其返回值的情況下岔乔,使用 then()
鏈來處理這個 Promise
對象酥筝。
testAsync().then(v => {
console.log(v); // 輸出 hello async
});
當(dāng) async
函數(shù)沒有返回值時,返回 Promise.resolve(undefined)
await
await
只能放在async
函數(shù)內(nèi)部使用
await
用于一個異步操作之前雏门,表示要“等待”這個異步操作的返回值嘿歌。
await
也可以用于一個同步的值掸掏。
如果它等到的不是一個 Promise
對象,那 await 表達式的運算結(jié)果就是它等到的東西宙帝。
如果它等到的是一個 Promise
對象丧凤,await
就會阻塞后面的代碼,等著 Promise
對象 resolve
步脓,然后得到 resolve
的值愿待,作為 await
表達式的運算結(jié)果。
同步代碼
const a = await 'hello world'
// 相當(dāng)于
const a = await Promise.resolve('hello world');
// 所以直接寫同步代碼即可沪编,不需要await關(guān)鍵字
const a = 'hello world';
異步代碼
// 2s 之后返回雙倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
})
}
async function testResult () {
let result = await doubleAfter2seconds(30);
console.log(result);
}
testResult();
// 2s 之后呼盆,輸出了60.
執(zhí)行順序
案例一
// 2s 之后返回雙倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
})
}
async function testResult () {
console.log('內(nèi)部調(diào)用前') // 2
let result = await doubleAfter2seconds(30);
console.log(result); // 4
console.log('內(nèi)部調(diào)用后') // 5
}
console.log('外部調(diào)用前') // 1
testResult();
console.log('外部調(diào)用后') // 3
// --- 依次輸出
// 外部調(diào)用前
// 內(nèi)部調(diào)用前
// 外部調(diào)用后
// --- 2s 之后輸出
// 60
// 內(nèi)部調(diào)用后
分析一下上面的執(zhí)行順序:
1、首先打印輸出外部調(diào)用前
蚁廓,同步代碼访圃,順序執(zhí)行。
2相嵌、然后調(diào)用方法testResult()
腿时,打印輸出內(nèi)部調(diào)用前
,同步代碼饭宾,順序執(zhí)行批糟。
3、再執(zhí)行異步方法doubleAfter2seconds
看铆,
1>如果沒用await
關(guān)鍵字徽鼎,此后的執(zhí)行順序應(yīng)該是
內(nèi)部調(diào)用后
,外部調(diào)用后
弹惦,2s 之后輸出60
因為異步方法不阻塞其他代碼的執(zhí)行否淤,最后再輸出60
2>這里使用了await
關(guān)鍵字,所以到這里后會等待異步返回結(jié)果棠隐,再往下執(zhí)行石抡。
4、當(dāng)testResult
函數(shù)內(nèi)部await
阻塞執(zhí)行后助泽,不會影響到testResult
函數(shù)外面
async
函數(shù)調(diào)用不會造成阻塞啰扛,它內(nèi)部所有的阻塞都被封裝在一個 Promise
對象中異步執(zhí)行。
所以嗡贺,在調(diào)用testResult
函數(shù)后隐解,會繼續(xù)向下執(zhí)行,打印輸出外部調(diào)用后
5诫睬、當(dāng)2s之后厢漩,異步函數(shù)doubleAfter2seconds
執(zhí)行完成,返回結(jié)果岩臣,
打印輸出60
6溜嗜、因為await
將異步變成同步,所以在輸出60
后架谎,同步執(zhí)行炸宵,再輸出內(nèi)部調(diào)用后
案例二
代碼
console.log("1")
異步處理函數(shù):console.log(2)
console.log(3)
結(jié)果
正常情況 132
用async await 123
例子
// 2s 之后返回雙倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
})
}
async function testResult () {
let first = await doubleAfter2seconds(10);
let second = await doubleAfter2seconds(20);
console.log(first + second);
}
錯誤處理
方式一 統(tǒng)一處理
// 2s 之后返回雙倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
})
}
async function testResult () {
let first = await doubleAfter2seconds(10);
let second = await doubleAfter2seconds(20);
let res = first + second;
return res;
}
testResult().then(res => {
console.log(res);
}).catch(error => {
console.log(error);
});
方式二 try...catch
// 2s 之后返回雙倍的值
function doubleAfter2seconds(num) {
return new Promise((resolve, reject) => {
setTimeout(() => {
resolve(2 * num)
}, 2000);
})
}
async function testResult () {
try {
let first = await doubleAfter2seconds(10);
let second = await doubleAfter2seconds(20);
let res = first + second;
return res;
} catch (error) {
console.log(error);
}
}
testResult()
在接口中使用(axios)
created () {
this.init()
},
methods: {
async init () {
try {
let first = await this.getOne();
let second = await this.getTwo();
let res = first + second;
console.log(res);
} catch (error) {
console.log(error);
}
},
getOne () {
const params = {name: 'one'}
return new Promise((resolve, reject) => {
axios.get('/one', { params}).then((res) => {
if (res.status === 200) {
resolve(res)
}
}).catch((err) => {
reject(err)
})
})
},
getTwo () {
const params = {name: 'two'}
return new Promise((resolve, reject) => {
axios.get('/two', { params}).then((res) => {
if (res.status === 200) {
resolve(res)
}
}).catch((err) => {
reject(err)
})
})
},
},