async await
async await
是异步编程的另一种解决方案async
函数是对Generator
函数的改进
async的基本用法
async函数
async
函数返回一个 Promise
实例,可以使用then
方法(为返回的Promise实例)添加回调函数。当函数执行的时候,一旦遇到await
就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
例 1:
上面代码是一个获取股票报价的函数,函数前面的
async
关键字,表明该函数内部有异步操作。调用该函数时,会立即返回一个Promise
实例。async
函数内部return
语句返回的值,会成为then
方法回调函数的参数。
Promise对象的状态变化
async
函数返回的 Promise
对象,必须等到内部所有await
命令后面的 Promise
对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async
函数内部的异步操作执行完,才会执行then
方法指定的回调函数。
await命令的基本用法
正常情况下,await
命令后面是一个Promise
实例,如果不是,会被转成一个立即resolve
的Promise
实例。
async function f() {
return await 123;
}
f().then(v => console.log(v))
等价于
async function f() {
return await new Promise(function(resolve){
resolve(123)
})
}
f().then(v => console.log(v))
等价于
async function f() {
return await Promise.resolve('123')
}
f().then(v => console.log(v))
await语句的返回值是await命令后面Promise实例的结果(异步处理的结果)
function getResult() {
return new Promise((resolve) => {
resolve('result: 1000') // resolve()方法的参数就是异步处理的结果
});
}
async function asyncPrint() {
const result = await getResult() // 将异步处理的结果赋值给result
return result
}
asyncPrint().then( (result) => { console.log(result) } ) //'result: 1000'
异常处理
如果await
后面的异步操作出错,那么等同于async
函数返回的 Promise
对象被reject
。
async function f() {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
}
f()
.then(v => console.log(v))
.catch(e => console.log(e))
// Error:出错了
防止出错的方法,也是将其放在try...catch代码块之中。
async function f() {
try {
await new Promise(function (resolve, reject) {
throw new Error('出错了');
});
} catch(e) {
}
return await('hello world');
}
使用注意
如果
await
后面的异步操作出错,那么等同于async
函数返回的Promise
对象被reject
,所以最好把await
命令放在try...catch
代码块中。
async function myFunction() {
try {
await somethingThatReturnsAPromise();
} catch (err) {
console.log(err);
}
}
// 另一种写法
async function myFunction() {
await somethingThatReturnsAPromise()
.catch(function (err) {
console.log(err);
});
}
多个
await
命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
let foo = await getFoo();
let bar = await getBar();
上面代码中,getFoo
和getBar
是两个独立的异步操作(即互不依赖),被写成继发关系(只有执行完getFoo操作,才能去执行getBar操作)。这样比较耗时,因为只有getFoo
完成以后,才会执行getBar
,完全可以让它们同时触发。
解释:这里的getFoo
和getBar
方法会返回两个Promise
实例(假设是发起Ajax请求,请求foo和bar的内容),只有执行了方法,对应的操作才会执行,如果写成上面的形式,就会导致执行完getFoo
的操作后(等待收到服务器的响应后),才能执行getBar
的操作,这样就成了同步,比较耗时,因此可以将上面的写法修改,使得在等待getFoo
执行完的时间内(在等待服务器响应的期间)去执行执行getBar
记住:当函数执行的时候,一旦遇到await就会先返回,等到异步操作完成,再接着执行函数体内后面的语句。
// 写法一
let [foo, bar] = await Promise.all([getFoo(), getBar()]);
// 写法二
let fooPromise = getFoo();
let barPromise = getBar();
let foo = await fooPromise;
let bar = await barPromise;
上面两种写法,getFoo
和getBar
都是同时触发,这样就会缩短程序的执行时间。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。