简介
async 异步函数是 ECMAScript 第七版(ES7)才被支援的语法,而目前还没被大部分的JavaScript Engine引入,如果需要使用需要使用babel
之类的工具;而异步函数和一般的函数一样,只不过可以在此函数内使用await的语法去执行并等待非同步工作(Promise),可以告别以往冗长的callback function。
async 和 await 是什么?
sync 是“异步”的简写,而await 可以认为是async wait 的简写,注意!!await只能出现在async函数中。
async的return?
async function testAsync() { return "hello async";}const result = testAsync();console.log(result);
输出 :
可以看到async函数return的是一个Promise Object,如果在async function中return一个直接的变数,async会通过Promise.resolve()将它封装成Promise,若在没有await的情况下执行async函数会"立即"执行返回一个Promise Object。
await ?
一般来说await是在等待一个async函数的完成,因为async函数return一个Promise Object,所以await可以用于等待一个async的return值。注意!!await不仅用于等Promise Object它也可以接普通函数或是直接的变数。
function getSomething() { return "something";}async function testAsync() { return Promise.resolve("hello async");}async function test() { const v1 = await getSomething(); const v2 = await testAsync(); console.log(v1, v2);}test();
由于await后面可以接普通的函数与直接变数,所以上面的程式是可以执行的。
结果:
async/await实例
以setTimeout模拟好费时间的非同步操作,先看看过去的写法:
function takeLongTime() { return new Promise(resolve => { setTimeout(() => resolve("long_time_value"), 1000); });}takeLongTime().then(v => { console.log("got", v);});
使用async/await写法 :
function takeLongTime() { return new Promise(resolve => { setTimeout(() => resolve("long_time_value"), 1000); });}async function test() { const v = await takeLongTime(); console.log(v);}test();
这两个程式都会在1秒后输出"long_time_value",注意!!由于async是return一个Promise,而function takeLongTime也是return一个Promise所以功能与async function takeLongTime()...一样。
async/await 的优势
使用async/await 写法的优势在于处理多个then,使用过去的Promise通过then来解决多层callback function会相对複杂,而使用async/await可以达到一样的效果并且比较直白,对于阅读与维护变得更为简单。
举一个例子,有一个程式中分许多个步骤,而每一个步骤都是非同步的,并且将上一个步骤地结果传给你下一个步骤当作输入参数。
function takeLongTime(n) { return new Promise(resolve => { setTimeout(() => resolve(n + 200), n); }); } function step1(n) { console.log(`step1 with ${n}`); return takeLongTime(n); } function step2(n) { console.log(`step2 with ${n}`); return takeLongTime(n); } function step3(n) { console.log(`step3 with ${n}`); return takeLongTime(n); }
使用Promise写法 :
function doIt(){ console.time("doIt"); const time1 = 300; step1(time1) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(result => { console.log(`result is ${result}`); console.timeEnd("doIt"); });};
使用async/await写法 :
doIt = async() => { console.time("doIt"); const time1 = 300; const time2 = await step1(time1); console.log("time2 = " + time2); const time3 = await step2(time2); console.log("time3 = " + time3); const result = await step3(time3); console.log(`result is ${result}`); console.timeEnd("doIt"); }; doIt();
结果 :
将time1传递给step1,经过300ms后会将非同步的结果(Promise.resolve)return给time2,而再将time2传入step2,经过(300+200)ms后return给time3,最后将time3传入step3中,经过(500+200)ms后return给result,所以总共耗时300 + 500 + 700 = 1500ms,使用async/await与Promise的结果一样,但程式码看起来清晰许多,方便阅读也方便维护。
参考资料 :
理解JavaScript 的async/await
JavaScript 好用的 async 异步函数!