Node.js 7的async / await

Node.js的发展越来越完善,解决单线程不能充分利用CPU的问题,而增加child_process模块,即可利用CPU的多核优势,而为了解决回调黑洞的问题,也诞生各种解决方案,比如在ES2016的中使用promise和generator,在ES7中的Ascny/Await,这可能也是最终的解决方案,现在Node.js 7即将发布,可以使用Node.js 7测试版(在没有正式发布前你可以使用Babel),体验Ascny/Await的特性

2 min read
By myfreax
Node.js 7的async / await

Node.js的发展越来越完善,解决单线程不能充分利用CPU的问题,而增加child_process模块,即可利用CPU的多核优势,而为了解决回调黑洞的问题,也诞生各种解决方案,比如在ES2016的中使用promise和generator,在ES7中的Ascny/Await,这可能也是最终的解决方案,现在Node.js 7即将发布,可以使用Node.js 7测试版(在没有正式发布前你可以使用Babel),体验Ascny/Await的特性

Async/Await

Ascny/Await关键词必须配合使用,await等待promise执行完成,这有点像ES2016的promise和generator的解决方案,yield promise后再传回generator

class Demo {
  async greeting() {
    let  h = await this.world();
    console.log(h); //hello world
  }
  world() {
    return Promise.resolve('hello world');
  }
}

除此之外async总是返回promise,在async的返回值作为promise的resolve方法的参数返回,比如在下面的示例中

async function asyncFun () {
  var value = await Promise
    .resolve(1)
    .then(x => x * 3)
    .then(x => x + 5)
    .then(x => x / 2);
  return value;
}
asyncFun().then(x => console.log(`x: ${x}`));
// <- 'x: 4'

因此也可以再次在async方法中await之前的async方法

async function combination() {
	let value = await  new Demo().greeting();
	console.log(value);
	
}
combination();

并行的异步任务

在异步的编程中,同时执行多个任务是常见的事情,在promise中可以使用promise.all同时执行多个异步任务,在async函数中也可以使用Promise.all

async function tasks () {
  let  [v1, v2] = await Promise.all([Promise.resolve(1), Promise.resolve(2)]);
  console.log(v1,v2);
}

//或者
const all = Promise.all.bind(Promise);
async function tasks () {
  let  [v1, v2] = await all([Promise.resolve(1), Promise.resolve(2)]);
  console.log(v1,v2);
}

在某些时候,你可以使用await*替代promise.all

async function tasks () {
  let  [v1, v2] = await* [Promise.resolve(1), Promise.resolve(2)];
  console.log(v1,v2);
}

错误处理

异步错误是不会被 try/catch捕获的,且在Node.js7之后一定处理promise的错误

async function read () {
    return await  new Promise((resolve, reject) => {
        request('http://www.myfreax.com/', (err, res, body) => {
            if (err) {
                reject(err); return;
            }
            resolve(body);
        });
    }).catch(error =>{
        throw new Error(error.stack);
    });

}