async await:用同步的方式來(lái)寫異步
async函數(shù)返回一個(gè) Promise 對(duì)象,可以使用then方法添加回調(diào)函數(shù)。函數(shù)內(nèi)部return語(yǔ)句返回的值,會(huì)成為then方法回調(diào)函數(shù)的參數(shù)。
當(dāng)async函數(shù)執(zhí)行的時(shí)候,一旦遇到await就會(huì)先返回,等到await的異步操作完成,再接著執(zhí)行函數(shù)體內(nèi)后面的語(yǔ)句。
async getAPI (value, ms) {
await new Promise((resolve, reject) => {
setTimeout(resolve, ms)
console.log(ms)
})
console.log(value)
}
//執(zhí)行
this.getAPI('hello', 1000)
console.log('雖然在后面,但是我先執(zhí)行')
//打印
1000
雖然在后面,但是我先執(zhí)行
間隔一秒打印 hello
由于async函數(shù)返回的是一個(gè)Promise 對(duì)象。也可改為
async getOne(ms) {
await new Promise((resolve, reject) => {
setTimeout(resolve, ms)
console.log(ms)
})
},
async getAPI(value, ms) {
await this.getOne(ms)
return value
}
// 執(zhí)行
this.getAPI('hello', 1000).then((res) => {
console.log(res)
})
console.log('雖然在后面,但是我先執(zhí)行')
// 打印結(jié)果一樣
通常await后面的函數(shù)是一個(gè)promise 對(duì)象。我們可以直接運(yùn)行async函數(shù)
如果await后面的函數(shù)不是一個(gè)promise,那他就會(huì)被轉(zhuǎn)成 Promise 對(duì)象,并立即resolve成為async返回的promise里面的參數(shù)
async function f() {
return await 123;
}
f().then(v => console.log(v))
// 123
await命令后面的 Promise 對(duì)象如果變?yōu)閞eject狀態(tài),則reject的參數(shù)會(huì)被catch方法的回調(diào)函數(shù)接收到。而resolve狀態(tài)卻不會(huì)被then方法接受(除非return)
async function f() {
await Promise.reject('出錯(cuò)了');
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// 出錯(cuò)了
只要有一個(gè)await語(yǔ)句后面的 Promise 變?yōu)閞eject,那么整個(gè)async函數(shù)都會(huì)中斷執(zhí)行。有時(shí),我們希望即使前一個(gè)異步操作失敗,也不要中斷后面的異步操作。這時(shí)可以將第一個(gè)await放在try...catch結(jié)構(gòu)里面,這樣不管這個(gè)異步操作是否成功,第二個(gè)await都會(huì)執(zhí)行。所以最好把a(bǔ)wait命令放在try...catch代碼塊中。
async getTrycatch() {
try {
await Promise.reject('error')
} catch (e) {}
return await Promise.resolve('reslove')
}
// 執(zhí)行
this.getTrycatch().then((res) => {
console.log(res)
})
應(yīng)用場(chǎng)景:多個(gè)異步接口的繼發(fā)
async getTwo() {
this.one = await getOne()
console.log(this.one)
this.two = await getTwo(this.one)
console.log(this.two)
}
多個(gè)接口的并發(fā)
let [one, two] = await Promise.all([getOne(), getTwo()])
this.one = one
this.two = two
多次重復(fù)嘗試
const superagent = require('superagent');
const NUM_RETRIES = 3;
async function test() {
for (let i = 0; i < NUM_RETRIES; i++) {
try {
await superagent.get('http://google.com/this-throws-an-error');
break;
} catch(err) {}
}
console.log(i); // 3
}
//上面代碼中,如果await操作成功,就會(huì)使用break語(yǔ)句退出循環(huán);如果失敗,會(huì)被catch語(yǔ)句捕捉,然后進(jìn)入下一輪循環(huán)。
總結(jié):
1.如果是一個(gè)異步函數(shù)我們就可以在他的函數(shù)名前加一個(gè)async,將函數(shù)體里的return new promise改為await new promise
2.將await代碼塊放入try{}catch(e){}中
3.await默認(rèn)是繼發(fā)的,并發(fā)要使用Promise.all([...])
4.安裝babel-polyfill解決不識(shí)別async await的問(wèn)題
*知識(shí)來(lái)源于http://es6.ruanyifeng.com/#docs/async,謝謝阮一峰老師