一、什么是async

async其实是ES7的才有的关键字,放在这里说,其实是和我们前面所说的Promise,Generator有很大关联的。async的意思是"异步",顾名思义是有关异步操作有关的关键字。下面我们就来构造一个async方法。

async function helloAsync(){return "helloAsync";}console.log(helloAsync())//Promise {<resolved>: "helloAsync"}

申明async方法比较简单,只需要在普通的函数前加上"async"关键字即可。我们执行下这个函数,发现并没有返回字符串"helloAsync",而是通过Promise.resolved()将字符串封装成了一个Promise对象返回。

既然是返回的Promise对象,我们就是用then方法来处理。

async function helloAsync(){return "helloAsync";}helloAsync().then(v=>{console.log(v);//"helloAsync"})

到这,道友们可能纳闷了,就是封装一个Promise的对象返回,这有个毛用啊。别急,await关键字闪亮登场。

二、await关键字

在Generator章节中我们熟悉了yield关键字,yield关键字只能使用在Generator函数中,同样,await关键字也不能单独使用,是需要使用在async方法中。 await字面意思是"等待",那它是在等什么呢?它是在等待后面表达式的执行结果。

function testAwait(){return new Promise((resolve) => {setTimeout(function(){console.log("testAwait");resolve();}, 1000);});}async function helloAsync(){await testAwait();console.log("helloAsync");}helloAsync();

我们来分析下这段代码

1、testAwait()方法中new一个Promise对象返回,promise对象中用setTimeout模拟一个异步过程,即1s后打印"testAwait"。

2、helloAsync()方法中,await testAwait(),表示将阻塞这里,等待testAwait这个异步方法执行并返回结果后,才继续下面的代码。

执行下,1s后打印了下面的日志。

到此,道友们是不是理解了await的作用,就是阻塞主函数的执行,直到后面的Promise函数返回结果。

聪明的道友可能要问,await后面只能 是Promise对象么?答案是否定的,可以是字符串,布尔值,数值以及普通函数。

function testAwait(){setTimeout(function(){console.log("testAwait");}, 1000);}async function helloAsync(){await testAwait();console.log("helloAsync");}helloAsync();

执行结果:

方法没有报错,说明await后面是支持非Promise函数的,但是执行的结果是不一样的,所以await针对所跟的表达式不同,有两种处理方式:

1、对于Promise对象,await会阻塞主函数的执行,等待 Promise 对象 resolve,然后得到 resolve 的值,作为 await 表达式的运算结果,然后继续执行主函数接下来的代码。

2、对于非Promise对象,await等待函数或者直接量的返回,而不是等待其执行结果。

我们知道Promise对象有两种状态,除了resolved,还有rejected,我们来看下如果promise对象变为rejected,会如何处理。

function testAwait(){return Promise.reject("error");}async function helloAsync(){await testAwait();console.log("helloAsync");//没有打印}helloAsync().then(v=>{console.log(v);}).catch(e=>{console.log(e);//"error"});

从执行结果看,返回reject状态被外层的catch捕获到,然后终止了后面的执行。

但是在有些情况下,出错后是希望继续执行,而不是中断。对于这种情况可以采用tcy...catch在函数内部捕获异常。

function testAwait(){return Promise.reject("error");}async function helloAsync(){try{await testAwait();}catch(e){console.log("this error:"+e)//this error:error}    console.log("helloAsync");//helloAsync}helloAsync().then(v=>{}).catch(e=>{console.log(e);//没有打印});

异常被try...catch捕获后,继续执行下面的代码,没有导致中断。

三、应用场景

上面说到,await可以阻塞主函数,直到后面的Promise对象执行完成。这个特性就能很轻松的解决按顺序控制异步操作,即我们前一章节讲的异步流程的问题。

道友们还记得在Generator章节的肚包鸡的制作过程的实例,我们用async/await来重写这个例子,并比较下两者实现的区别。

//准备function prepare(){return new Promise((resolve) => {setTimeout(function(){console.log("prepare chicken");resolve();},500)});  }//炒鸡function fired(){return new Promise((resolve) => {setTimeout(function(){console.log("fired chicken");resolve();},500)}); }//炖鸡function stewed(){return new Promise((resolve) => {setTimeout(function(){console.log("stewed chicken");resolve();},500)}); }//上料function sdd(){return new Promise((resolve) => {setTimeout(function(){console.log("sdd chicken");resolve();},500)}); }//上菜function serve(){return new Promise((resolve) => {setTimeout(function(){console.log("serve chicken");resolve();},500)});}async function task(){console.log("start task");await prepare();await fired();await stewed();await sdd();await serve();console.log("end task");}task();

这段代码看上去神清气爽,我们来分析下代码:

1、首先每个制作异步过程封装成Promise对象。

2、利用await阻塞原理,实现每个制作的顺序执行。

相比较Generator实现,无需run流程函数,完美的实现了异步流程。

四、总结

从Promise到Generator,再到async,对于异步编程的解决方案越来越完美,这就是ES6不断发展的魅力所在。

上一篇:ES6系列教程第三篇--Generator 详解                          下一篇:ES6系列教程第五篇--Class(一)

ES6系列教程第四篇--asyn详解相关推荐

  1. ES6系列教程第三篇--Generator 详解

    一.什么是Generator 函数 先看下面的Generator函数, function* helloGenerator() {console.log("this is generator& ...

  2. Android系列教程之七:EditText使用详解-包含很多教程上看不到的功能演示

    写道 标题有点大,说是详解,其实就是对EditText的一些常用功能的介绍,包括密码框,电话框,空白提示文字等等的讲解,尽量的介绍详细一点,也就是所谓的详解了..呵呵 广告一下我的应用"我团 ...

  3. 机器学习第四篇:详解决策树算法

    01|背景: 我们在日常生活中经常会遇到一些选择需要去做一些选择,比如我们在找工作的时候每个人都希望能找到一个好的工作,但是公司那么多,工作种类那么多,什么样的工作才能算是好工作,这个时候就需要我们对 ...

  4. eureka集群只注册一个_Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇

    Spring cloud系列教程第十篇- Spring cloud整合Eureka总结篇 本文主要内容: 1:spring cloud整合Eureka总结 本文是由凯哥(凯哥Java:kagejava ...

  5. 【NLP】四万字全面详解 | 深度学习中的注意力机制(四,完结篇)

    作者 | 蘑菇先生 知乎 | 蘑菇先生学习记 深度学习Attention小综述系列: 四万字全面详解 | 深度学习中的注意力机制(一) 四万字全面详解 | 深度学习中的注意力机制(二) 四万字全面详解 ...

  6. graphviz 画决策树_数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris

    数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iris 加载数据集 数据特征 训练 随机森林 调参工程师 结尾 数据挖掘入门系列教程(四)之基于scikit-lean决策树处理Iri ...

  7. html5游戏制作入门系列教程(四)

    今天,我们继续一系列文章,使用HTML5的canvas组件进行游戏开发.今天我们要学习下元素:声音控制与动画.在我们的演示中,你会 看到一个飞龙.我们会听到持续的翅膀拍打的声音(我们将循环这个声音), ...

  8. ASP.NET 5系列教程(七)完结篇-解读代码

     在本文中,我们将一起查看TodoController 类代码. [Route] 属性定义了Controller的URL 模板: [Route("api/[controller]&quo ...

  9. OpenCV学习系列教程第五篇:测试和提高代码的效率

    Opencv-Python学习系列教程第五篇 来自opencv-python官方学习文档,本人谨做翻译和注释,以及一些自己的理解 本文由作者翻译并进行代码验证,转载请注明出处~ 官方文档请参阅:htt ...

最新文章

  1. ADAS处理器集成功能安全单片机MCU
  2. java 中lock,java中lock获取锁的四种方法
  3. 【廖雪峰python入门笔记】迭代
  4. 一款图像相关软件PhoXo
  5. android 开机启动服务。
  6. 单例模式volatile
  7. mysqld_multi单机启动多个mysql
  8. libvirt API管理hypervisors
  9. 使用知行之桥® EDI系统对接德州仪器TI
  10. 金盾高级视频加密系统使用教程与经验分享 (金盾视频加密系统跨平台版)
  11. OpenStack环境下安装Mistral
  12. win7 计算机定时关机脚本,Win7定时关机命令 win7系统怎么设置定时关机
  13. 如何启动联想计算机的休眠模式,如何设置休眠、待机、睡眠
  14. 微信图片去除马赛克_怎么给图片打上马赛克(模糊处理、涂抹)
  15. Oracle导出表结构(含表名、字段名、数据类型、是否为空、字段说明)至Excel(简单详细)sql语句的形式
  16. 5大输入法突然下架!得知真相的网友懵了:我都用了10年了……
  17. Java+SSM+JSP实现医院预约挂号系统
  18. [java 新手练习1]5x5横排竖排方阵代码(java)
  19. 算法竞赛入门经典(第2版)—第五章(C++与STL入门)
  20. Maven ArtifactDescriptorException: Failed to read artifact descriptor for com.sun.mail 异常

热门文章

  1. 解决mac电脑上的浏览器和应用Trello无法登陆的问题
  2. MySQL打开时在命令行输入密码后,按回车键闪退,快速解决方法
  3. Docker常用命令记录
  4. Linux虚拟机设置双网卡
  5. 【LaTeX 教程】05. LaTeX 插入图片
  6. matlab 函数 c++ 复写之randperm
  7. TI/德州仪器 TPS3808G30DBVT 微处理器
  8. CSS 样式优先级权重
  9. idea集成Tomcat的错误(换了一个新的环境.)
  10. 修改Centos的英文显示为中文显示