async / await是ES7的重要特性之一,也是目前社区里公认的优秀异步解决方案。目前,async / await这个特性已经是stage 3的建议,可以看看TC39的进度,本篇文章将分享async / await是如何工作的,阅读本文前,希望你具备Promise、generator、yield等ES6的相关知识。

在详细介绍async / await之前,先回顾下目前在ES6中比较好的异步处理办法。下面的例子中数据请求用Node.js中的request模块,数据接口采用Github v3 api文档提供的repo代码仓库详情API作为例子演示。
Promise对异步的处理
虽然Node.js的异步IO带来了对高并发的良好支持,同时也让“回调”成为灾难,很容易造成回调地狱。传统的方式比如使用具名函数,虽然可以减少嵌套的层数,让代码看起来比较清晰。但是会造成比较差的编码和调试体验,你需要经常使用用ctrl + f去寻找某个具名函数的定义,这使得IDE窗口经常上下来回跳动。使用Promise之后,可以很好的减少嵌套的层数。另外Promise的实现采用了状态机,在函数里面可以很好的通过resolve和reject进行流程控制,你可以按照顺序链式的去执行一系列代码逻辑了。下面是使用Promise的一个例子:
const request = require('request');
// 请求的url和header
const options = {
url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
headers: {
'User-Agent': 'request'
}
};
// 获取仓库信息
const getRepoData = () => {
return new Promise((resolve, reject) => {
request(options, (err, res, body) => {
if (err) {
reject(err);
}
resolve(body);
});
});
};
getRepoData()
.then((result) => console.log(result);)
.catch((reason) => console.error(reason););
// 此处如果是多个Promise顺序执行的话,如下:
// 每个then里面去执行下一个promise
// getRepoData()
// .then((value2) => {return promise2})
// .then((value3) => {return promise3})
// .then((x) => console.log(x))
不过Promise仍然存在缺陷,它只是减少了嵌套,并不能完全消除嵌套。举个例子,对于多个promise串行执行的情况,第一个promise的逻辑执行完之后,我们需要在它的then函数里面去执行第二个promise,这个时候会产生一层嵌套。另外,采用Promise的代码看起来依然是异步的,如果写的代码如果能够变成同步该多好啊!
Generator对异步的处理
谈到generator,你应该不会对它感到陌生。在Node.js中对于回调的处理,我们经常用的TJ / Co就是使用generator结合promise来实现的,co是coroutine的简称,借鉴于python、lua等语言中的协程。它可以将异步的代码逻辑写成同步的方式,这使得代码的阅读和组织变得更加清晰,也便于调试。
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);
});
async / await对异步的处理
虽然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
这里推荐使用babel官方提供的require hook方法。就是通过require进来后,接下来的文件进行require的时候都会经过Babel的处理。因为我们知道CommonJs是同步的模块依赖,所以也是可行的方法。这个时候,需要编写两个文件,一个是启动的js文件,另外一个是真正执行程序的js文件。
启动文件index.js
require('babel-core/register');
require('./async.js');
真正执行程序的async.js
const request = require('request');
const options = {
url: 'https://api.github.com/repos/cpselvis/zhihu-crawler',
headers: {
'User-Agent': 'request'
}
};
const getRepoData = () => {
return new Promise((resolve, reject) => {
request(options, (err, res, body) => {
if (err) {
reject(err);
}
resolve(body);
});
});
};
async function asyncFun() {
try {
const value = await getRepoData();
// ... 和上面的yield类似,如果有多个异步流程,可以放在这里,比如
// const r1 = await getR1();
// const r2 = await getR2();
// const r3 = await getR3();
// 每个await相当于暂停,执行await之后会等待它后面的函数(不是generator)返回值之后再执行后面其它的await逻辑。
return value;
} catch (err) {
console.log(err);
}
}
asyncFun().then(x => console.log(`x: ${x}`)).catch(err => console.error(err));
注意点:
其实,async / await的用法和co差不多,await和yield都是表示暂停,外面包裹一层async 或者 co来表示里面的代码可以采用同步的方式进行处理。不过async / await里面的await后面跟着的函数不需要额外处理,co是需要将它写成一个generator的。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# js中的await
# async
# js
# await
# async用法
# JavaScript中使用Async实现异步控制
# async/await与promise(nodejs中的异步操作问题)
# JavaScript无阻塞加载和defer、async详解
# JavaScript中的await/async的作用和用法
# 关于Javascript中defer和async的区别总结
# JS中script标签defer和async属性的区别详解
# 浏览器环境下JavaScript脚本加载与执行探析之defer与async特性
# 理解javascript async的用法
# 多个
# 放在
# 是一个
# 回调
# 很好
# 返回值
# 这个时候
# 链式
# 后会
# 用在
# 的是
# 都是
# 层数
# 是在
# 还没有
# 你可以
# 第一个
# 多好
# 就有
# 不需要
相关文章:
如何配置支付宝与微信支付功能?
如何通过远程VPS快速搭建个人网站?
如何在腾讯云免费申请建站?
常州自助建站:操作简便模板丰富,企业个人快速搭建网站
正规网站制作公司有哪些,目前国内哪家网页网站制作设计公司比较专业靠谱?口碑好?
岳西云建站教程与模板下载_一站式快速建站系统操作指南
如何用好域名打造高点击率的自主建站?
详解一款开源免费的.NET文档操作组件DocX(.NET组件介绍之一)
MySQL查询结果复制到新表的方法(更新、插入)
如何选择靠谱的建站公司加盟品牌?
制作网站外包平台,自动化接单网站有哪些?
网站制作员失业,怎样查看自己网站的注册者?
网站制作的方法有哪些,如何将自己制作的网站发布到网上?
如何用花生壳三步快速搭建专属网站?
广东专业制作网站有哪些,广东省能源集团有限公司官网?
内部网站制作流程,如何建立公司内部网站?
常州企业建站如何选择最佳模板?
实现虚拟支付需哪些建站技术支撑?
电视网站制作tvbox接口,云海电视怎样自定义添加电视源?
车管所网站制作流程,交警当场开简易程序处罚决定书,在交警网站查询不到怎么办?
建站之星展会模版如何一键下载生成?
jQuery 常见小例汇总
利用JavaScript实现拖拽改变元素大小
音响网站制作视频教程,隆霸音响官方网站?
淘宝制作网站有哪些,淘宝网官网主页?
如何通过FTP服务器快速搭建网站?
Dapper的Execute方法的返回值是什么意思 Dapper Execute返回值详解
如何在云主机快速搭建网站站点?
SQL查询语句优化的实用方法总结
如何在Windows服务器上快速搭建网站?
做企业网站制作流程,企业网站制作基本流程有哪些?
如何在阿里云服务器自主搭建网站?
制作网页的网站有哪些,电脑上怎么做网页?
建站主机选虚拟主机还是云服务器更好?
用v-html解决Vue.js渲染中html标签不被解析的问题
SAX解析器是什么,它与DOM在处理大型XML文件时有何不同?
专业的网站制作设计是什么,如何制作一个企业网站,建设网站的基本步骤有哪些?
建站之星备案流程有哪些注意事项?
如何选择适配移动端的WAP自助建站平台?
网站制作外包价格怎么算,招聘网站上写的“外包”是什么意思?
制作旅游网站html,怎样注册旅游网站?
深圳网站制作公司好吗,在深圳找工作哪个网站最好啊?
logo在线制作免费网站在线制作好吗,DW网页制作时,如何在网页标题前加上logo?
详解jQuery停止动画——stop()方法的使用
如何用y主机助手快速搭建网站?
如何在IIS中新建站点并配置端口与IP地址?
红河网站制作公司,红河事业单位身份证如何上传?
怎么制作网站设计模板图片,有电商商品详情页面的免费模板素材网站推荐吗?
建站之星3.0如何解决常见操作问题?
如何快速生成凡客建站的专业级图册?
*请认真填写需求信息,我们会在24小时内与您取得联系。