async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案。目前,async / await这个特性已经是stage 3的建议。
(1)Promise、generator、yield是ES6中的异步解决方案,使用Promise之后,可以很好的减少嵌套的层数。
function fn(p) { return new Promise((resolve, reject) => { console.log(p); setTimeout(() => { console.log(‘test:‘,p); resolve(); }, 2000); }); } function handlePromise() { fn("aaa") .then(() => { return fn("bbb"); }) .then(() => { return fn("ccc"); }) .catch(reason => console.log(`catch reason: ${reason}`)); } 执行:handlePromise()
Promise仍然存在缺陷,它只是减少了嵌套,并不能完全消除嵌套。对于多个promise串行执行的情况,第一个promise的逻辑执行完之后,我们需要在它的then函数里面去执行第二个promise,这个时候会产生一层嵌套。另外,采用Promise的代码看起来依然是异步的!
(2)在Node.js中对于回调的处理,我们经常用的TJ / Co就是使用generator结合promise来实现的,co是coroutine的简称。
const co = require(‘co‘); const request = require(‘request‘); const options = { url: ‘https://api.github.com/repos/cpselvis/zhihu-crawler‘, headers: { ‘User-Agent‘: ‘request‘ } }; // yield后面是一个生成器 generator const getRepoData = function* () { return new Promise((resolve, reject) => { request(options, (err, res, body) => { if (err) { reject(err); } resolve(body); }); }); }; co(function* () { const result = yield getRepoData; // ... 如果有多个异步流程,可以放在这里,比如 // const r1 = yield getR1; // const r2 = yield getR2; // const r3 = yield getR3; // 每个yield相当于暂停,执行yield之后会等待它后面的generator返回值之后再执行后面其它的yield逻辑。 return result; }).then(function (value) { console.log(value); }, function (err) { console.error(err.stack); });
(3)虽然co是社区里面的优秀异步解决方案,但是并不是语言标准,只是一个过渡方案。
ES7语言层面提供async / await去解决语言层面的难题。目前async / await 在 IE edge中已经可以直接使用了,但是chrome和Node.js还没有支持。
幸运的是,babel已经支持async的transform了,所以我们使用的时候引入babel就行。
在开始之前我们需要引入以下的package,preset-stage-3里就有我们需要的async/await的编译文件。
无论是在Browser还是Node.js端都需要安装下面的包。
$ npm install babel-core --save $ npm install babel-preset-es2015 --save $ npm install babel-preset-stage-3 --save
function fn(p) { return new Promise((resolve, reject) => { console.log(p); setTimeout(() => { console.log(‘test:‘,p); resolve(); }, 2000); }); } // 注意点: // 1.async用来申明里面包裹的内容可以进行同步的方式执行,await则是进行执行顺序控制, // 每次执行一个await,程序都会暂停等待await返回值,然后再执行之后的await。 // 2.await后面调用的函数需要返回一个promise,另外这个函数是一个普通的函数即可,而不是generator。 // 3.await只能用在async函数之中,用在普通函数中会报错。 // 4.await命令后面的 Promise 对象,运行结果可能是 rejected,所以最好把 await 命令放在 try...catch 代码块中。 // 5.其实,async / await的用法和co差不多,await和yield都是表示暂停, // 外面包裹一层async 或者 co来表示里面的代码可以采用同步的方式进行处理。 // 不过async / await里面的await后面跟着的函数不需要额外处理,co是需要将它写成一个generator的。 async function asyncFun() { try { const result_a = await fn(‘aaa‘); const result_b = await fn(‘bbb‘); const result_c = await fn(‘ccc‘); const result_d = await fn(‘ddd‘); // 每个await相当于暂停,执行await之后会等待它后面的函数(不是generator)返回值之后再执行后面其它的await逻辑。 return result_d; } catch (err) { console.log(err); } } 执行:asyncFun().then(result => console.log(`result: ${result}`)).catch(err => console.error(err));
参考:
http://www.cnblogs.com/cpselvis/p/6344122.html
http://caibaojian.com/es6/generator.html
原文:https://www.cnblogs.com/fengyouqi/p/10838573.html