JS中的异步操做从最初的回调函数演进到Promise,再到Generator,都是逐步的改进,而async函数的出现仿佛看到了异步方案的终点,用同步的方式写异步。ajax
原文连接promise
简单解释async函数就是Generator函数的语法糖。异步
Generator函数写法async
let promise = function (val){ return new Promise(function (resolve, reject){ setTimeout(()=>{ console.log(val); resolve(val); },1000); }); }; let gen = function* (){ let p1 = yield promise('1'); let p2 = yield promise('2'); }; let genF = gen();
async函数写法函数
let promise = function (val){ return new Promise(function (resolve, reject){ setTimeout(()=>{ console.log(val); resolve(val); },1000); }); }; let gen = async function (){ let p1 = await promise('1'); let p2 = await promise('2'); };
async函数是在Generator函数上进行的改进,语法上Generator函数的星号换成了async,yield换成了await。
而async也与Generator函数不一样:spa
寄予async函数的指望是但愿能够帮助咱们解决异步操做问题,因此须要搞清楚async函数的返回值是什么。code
async function asyncAwait() { return 'async await'; } let a = asyncAwait(); console.log(a);
结果输出:对象
Promise {<resolved>: "async await"}
能够看出async函数返回的是一个Promise对象,若是函数中return一个直接量,async函数会封装成Promise对象返回,而若是没有返回值时,async函数会返回undefinedrem
Promise {<resolved>: undefined}
在没有结合await时,async函数会当即执行,返回一个Promise对象。字符串
await是个运算符,等待的结果是Promise对象或其余值,好比:
function func1() { return 'async'; } async function func2() { return Promise.resolve('await'); } async function asyncAwait() { let f1 = await func1(); let f2 = await func2(); console.log(f1, f2); } asyncAwait()
结果输出:
async await
await表达式的运算取决于等待的结果,若是它等到的不是一个Promise对象,那运算结果就是它等到的东西,
而若是它等到的是一个Promise对象,它会阻塞后面的代码,等着Promise对象resolve,而后获得resolve的值,做为表达式的运算结果。
async函数调用会封装在Promise中,这也是await须要在async函数中使用的缘由。
对于多个异步操做中,Promise的then能够解决多层回调问题。
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t) { console.log(`step1 in ${t}ms`); return ajax(t); } function step2(t) { console.log(`step2 in ${t}ms`); return ajax(t); } function step3(t) { console.log(`step3 in ${t}ms`); return ajax(t); } function submit(){ console.time('submit'); step1(200) .then(time2 => step2(time2)) .then(time3 => step3(time3)) .then(result => { console.log(`result is ${result}ms`); console.timeEnd("submit"); }); } submit();
async函数实现:
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t) { console.log(`step1 in ${t}ms`); return ajax(t); } function step2(t) { console.log(`step2 in ${t}ms`); return ajax(t); } function step3(t) { console.log(`step3 in ${t}ms`); return ajax(t); } async function submit(){ console.time('submit'); const t1 = 200; const t2 = await step1(t1); const t3 = await step2(t2); const result = await step3(t3); console.log(`result is ${result}`); console.timeEnd('submit'); } submit();
结果输出:
step1 in 200ms step2 in 400ms step3 in 600ms result is 800 submit: 1209.85107421875ms
而若是需求变动,每一步的参数都是以前步骤的结果后,async函数能够写成:
function ajax(t) { return new Promise(resolve => { setTimeout(() => resolve(t + 200), t); }); } function step1(t1) { console.log(`step1 in ${t1}ms`); return ajax(t1); } function step2(t1, t2) { console.log(`step2 in ${t1}ms,${t2}ms`); return ajax(t1 + t2); } function step3(t1, t2, t3) { console.log(`step3 in ${t1}ms,${t2}ms,${t3}ms`); return ajax(t1 + t2 + t3); } async function submit(){ console.time('submit'); const t1 = 200; const t2 = await step1(t1); const t3 = await step2(t1, t2); const result = await step3(t1, t2, t3); console.log(`result is ${result}`); console.timeEnd('submit'); } submit();
结果输出:
step1 in 200ms step2 in 200ms,400ms step3 in 200ms,400ms,800ms result is 1600 submit: 2210.47998046875ms
async function asyncAwait() { try { await promise(); } catch (err) { console.log(err); } } // 另外一种写法 async function asyncAwait() { await promise().catch(function (err){ console.log(err); }); }
async/await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案,当你深刻了解原理后会发现仿佛看到了异步回调隧道的尽头亮光。