上一篇《让 Generator 自启动》介绍了通过起动器让 Generator 跑起来,而本篇采用 async 实现更优雅的异步编程。
从例子开始
借用上一篇例子中的例子说起。
function* gen() {
var r1 = yield $.get('url1');
var r2 = yield $.get('url2');
var r3 = yield $.get('url3');
console.log(r1, r2, r3);
}
然后,我们需要写一个启动器来启动这个函数。
而采用 async 写,代码则是:
async function gen() {
var r1 = await $.get('url1');
var r2 = await $.get('url2');
var r3 = await $.get('url3');
console.log([r1, r2, r3].join('
'));
}
gen(); // 直接运行即可
直接运行了,无须写生成器来运行了,而代码仅仅是 *
改为 async
, yield
改为 await
而已。
所以本质上讲:async 就是 Generator 的语法糖。
多任务处理
多任务处理有个坑,就是不能直接在 forEach
, map
之类的方法里处理,否则会报错或者得到错误的结果。
function sleep(t) {
return new Promise(resolve => setTimeout( _ => { resolve(+new Date) }, t))
}
async function run() {
// 顺序
let a = await sleep(100)
let b = await sleep(200)
// 并发1
let c = await Promise.all([sleep(100), sleep(200), sleep(300)])
// 并发2
let d = await Promise.all([100, 200, 300].map(t => sleep(t)))
// 并发3
let list = [sleep(100), sleep(200), sleep(300)]
let e = []
for (let fn of list) {
e.push(await fn)
}
console.log(
'',
'a:', a, '
',
'b:', b, '
',
'c:', c, '
',
'd:', d, '
',
'e:', e, '
'
)
}
run()
// a: 1468317737179
// b: 1468317737384
// c: [ 1468317737485, 1468317737589, 1468317737688 ]
// d: [ 1468317737792, 1468317737890, 1468317737989 ]
// e: [ 1468317738094, 1468317738193, 1468317738293 ]
小结
async 没多大的变动,归根结底就是个语法糖,帮助我们运行生成器,而不需要我们自己写起动器了。
不过效果确实非常好,让异步编程更加的同步
了。