async await
是异步编程的另外一种解决方案es6
async
函数是对Generator
函数的改进编程
async
函数返回一个 Promise
实例,能够使用then
方法(为返回的Promise实例)添加回调函数。当函数执行的时候,一旦遇到await
就会先返回,等到异步操做完成,再接着执行函数体内后面的语句。服务器
例 1:异步
上面代码是一个获取股票报价的函数,函数前面的async
关键字,代表该函数内部有异步操做。调用该函数时,会当即返回一个Promise
实例。async
async
函数内部return
语句返回的值,会成为then
方法回调函数的参数。异步编程
async
函数返回的 Promise
对象,必须等到内部全部await
命令后面的 Promise
对象执行完,才会发生状态改变,除非遇到return语句或者抛出错误。也就是说,只有async
函数内部的异步操做执行完,才会执行then
方法指定的回调函数。函数
正常状况下,await
命令后面是一个Promise
实例,若是不是,会被转成一个当即resolve
的Promise
实例。spa
async function f() { return await 123; } f().then(v => console.log(v))
等价于code
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
都是同时触发,这样就会缩短程序的执行时间。