前言
async/await产生原因:如果需要从多个数据库或者接口按顺序异步获取数据,最终会写出一坨纠缠不清的promise与回调。(鉴于本宝宝刚刚开始接触promise,这种糟心情况根本还没见识过……)
简单学习一下promise
一个promise抽象表达了一个非阻塞(阻塞指一个任务开始后,要等待该任务执行结果产生之后才继续执行后续任务)的异步流程,最典型的使用场景是网络或其他I/O操作(如读取一个文件或者发送一个HTTP请求)。promise用then方法来附加一个回调,用于执行该promise完成之后要做的事情。回调自身也可以返回一个promise,如此就可以将多个promise串联。
要使用promise,首先引入request-promise库:
1 | var rp = require('request-promise'); |
(所以……更前一步是npm i下载个么?)
然后发送一个简单的HTTP GET请求并获得一个promise返回值:
1 | console.log('Starting Execution'); // 第一处输出 |
在第一处输出后,第三处输出与这个get命令(虽然本宝宝不认识这个库的写法……)一起进行————“promise之后的代码跟promise自身是并发的”;直到这个get获得了(成功的)返回结果,再进行第二处输出。
*然后好欣慰,认出了ES6的箭头函数,虽然其实没有这么写的习惯……(跑题了)
JS中不存在一种方法可以让当前的执行流程阻塞直到promise完成,唯一可以用于提前计划promise完成后的执行逻辑的方式就是通过then附加回调函数。
然后如果这个请求失败了捏(比如网络异常了)?或者在then里面我们写错了什么导致了错误?这个时候就会转到catch里了~所以完整的可以这么写:
1 | rp('http://example.com/'). |
*Promise.resolve、Promise.reject要去了解一下,返回一个假定肯定走成功或者失败路线的promise
纠在一起的组合promise
假设一个命题,请实现以下逻辑:
- 发起一个HTTP请求,等待结果并将其输出
- 再发起两个并发的HTTP请求
- 当两个请求都完成时,一起输出他们
解答:
1 | // 第一次请求 |
Async函数
async函数是定义返回promise的函数的简便写法。
1 | // 成功的请求 |
Await
一个操作本身就是异步的(比如用promise包装的),它应该具备能力等待另一个异步操作先完成。但是JS解释器如何知道一个操作是不是在一个promise里的?
答案就是async关键字,所有的async函数一定会返回一个promise。所以,JS解释器也可以确信async函数里操作是用promise包装的异步过程。于是也就可以允许它等待其他promise。
键入await关键字,它只能在async函数内使用,让我们可以等待一个promise。如果在async函数外使用promise,我们依然需要使用then和回调函数:
1 | async function f(){ |
这时候上面那个问题可以这么来:
1 | async function solution() { |
计算流程跟之前的图表描绘的一样,但是代码变得更加已读与直白。
事实上,async/await其实会翻译成promise与then回调(译者:babel其实是翻译成generator语法,再通过类似co的函数运行,co内部运行机制离不开promise)。每次我们使用await,解释器会创建一个promise然后把async函数的后续代码放到then回调里。(所以,前面call2Promise和call3Promise其实还是先等待到call2Promise再去等待call3Promise?等待的用词有点不太对可能)
错误处理
async函数如果await的对象失败了呢?这可以用try/catch处理:
1 | async function f() { |
一些补充
作者的建议做法:把大部分的异步逻辑封装在一个或少量几个async函数里,然后在非async的代码区域里使用,这样就可以尽量减少书写then或catch回调。
并发(concurrent)与并行(parallel)是有区别的:
并发是组合多个独立过程来一起工作,并行是多个过程同时执行。
并发是体现在应用的结构设计,并行是实际执行的方式。
举个例子:
将应用分割成多个线程是该应用并发模型的定义,将这些线程放到多个cpu核心上一起执行是确立它的并行。一个并发的系统也可以在一个单核处理器上正常运行,但这种情况并不是并行。
恩,所以promise是一个将程序分解成多个并发的模块的工具,但不能保证在执行时是否并行,这要看解释器自身的实现(比如单线程的NodeJS去执行)。
致谢: