[转] js async await 终极异步解决方案
阅读目录
既然有了promise 为什么还要有async await ? 当然是promise 也不是完美的异步解决方案,而 async await 的写法看起来更加简单且容易理解。
回顾 Promise
Promise 对象用于表示一个异步操作的最终状态(完成或失败),以及其返回的值。
Promise 对象是由关键字 new 及其构造函数来创建的。构造函数会,把一个叫做“处理器函数”(executor function)的函数作为它的参数。这个“处理器函数”接受两个函数resolve 和 reject 作为其参数。当异步任务顺利完成且返回结果值时,会调用 resolve 函数,而当异步任务失败且返回失败原因(通常是一个错误对象)时,会调用reject 函数。
promise 状态
pending:初始状态,既不是成功,也不是失败状态
fulfilled:操作成功
rejected:操作失败
promise demo

1 var promise1 = new Promise(function(resolve, reject) {
2 setTimeout(function() {
3 resolve('foo');
4 }, 300);
5 });
6 promise1.then(function(value) {
7 console.log(value);
8 // foo
9 });
10 console.log(promise1);
11 // [object Promise]

通过外部then() 方法来绑定成功、失败的回调函数,有没有感觉这个跟之前的ajax 差不多,只不过是我们把回调丢到了then() 中,这个then 并且支持链式操作,即如果存在多个嵌套那么也就是不断的then()。
async await 字面理解
先从字面意思来理解,async 是“异步”的意思,而 await 是等待的意思。所以应该很好理解 async 用于申明一个 异步的function(实际上是async function 对象),而 await 用于等待一个异步任务执行完成的的结果。
并且 await 只能出现在 async 函数中。
async await demo
1 在api中,把结果return 出去
2 export async function getRetailUnitPrice () {
3 const reqBody = await get('/race/spot/racespot/enter/dayahead')
4 return reqBody
5 }
1 vuex 中把结果commit:
2 // 发电:日前机组中标出力
3 async getRealTimeRetailUnitPrice ({commit}) {
4 const {output} = await getRetailUnitPrice()
5 commit(types.PLANT_REALTIME_DAYAHEAD, {output})
6 }
1 在vue中代码
2 try {this.$store.dispatch('getRealTimeRetailUnitPrice')
3 } catch (e) {
4 this.$Message.error(e)
5 }
async、await 如何执行
async 告诉程序这是一个异步操作,await 是一个操作符,即 await 后面是一个表达式。
async 的返回值
1 // async
2 async function testAsync() {
3 return "hello async";
4 }
5 const data = testAsync();
6 console.log(data);
如图所示:
当调用一个 async 函数时,会返回一个 Promise 对象。根据mdn的解释
当这个 async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;
当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值。async 函数中可能会有 await 表达式,await表达式会使 async 函数暂停执行,直到表达式中的 Promise 解析完成后继续 执行 async中await 后面的代码并返回解决结果。
注意, await 关键字仅仅在 async function中有效
既然返回的是Promise 对象,所以在最外层不能用 await 获取其返回值的情况下,那么肯定可以用原来的方式:then() 链来处理这个 Promise 对象 如

1 // async
2 async function testAsync() {
3 return "hello async";
4 }
5 let data = testAsync().then( (data) => {
6 console.log(data) // hello async
7 return data
8 });
9 console.log(data);

如果 async 函数没有返回值,又怎么样呢?很容易想到,它会返回 Promise.resolve(undefined)。
联想一下 Promise 的特点无等待,所以在没有 await 的情况下执行 async 函数,它会立即执行,返回一个 Promise 对象,并且,绝不会阻塞后面的语句。
await 操作符
MDN 是这样描述 await 的:
await 表达式会暂停当前 async function 的执行,等待 Promise 处理完成。若 Promise 正常处理(fulfilled),其回调的resolve函数参数作为 await 表达式的值,继续执行async function。若 Promise 处理异常(rejected),await 表达式会把 Promise 的异常原因抛出。另外,如果 await 操作符后的表达式的值不是一个 Promise,则返回该值本身。
阮一峰老师的解释我觉得更容易理解:
async 函数返回一个 Promise 对象,当函数执行的时候,一旦遇到 await 就会先返回,等到触发的异步操作完成,再接着执行函数体内后面的语句。
按照mdn解释 await会暂停当前async 函数执行,并且await 后面是一个表达式,即这个await 等待的是一个表达式(这个表达式返回promise 对象或者一个具体的值):
- 假如这个表达式如果返回的是一个Promise 对象, 那么它的返回值,实际上就是 Promise 的回调函数 resolve 的参数,如果这个Promise rejected 了,await 表达式会把 Promise 的异常抛出。
- 假如这个表达式如果返回的是一个常量,那么会把这个常量转为Promise.resolve(xx),同理如果没有返回值也是Promise.resolve(underfind)
1 async function testAwait() {
2 const data = await "hello await";
3 console.log(data)
4 return data
5 }
输出 “hello await”
返回promose 对象,成功状态

1 function say() {
2 return new Promise(function(resolve, reject) {
3 setTimeout(function() {
4 let age = 26
5 resolve(`hello, joel。今年我 ${age} 岁`);
6 }, 1000);
7 });
8 }
9
10 async function demo() {
11 const v = await say(); // 输出:hello, joel。今年我 26 岁 等待这个say 的异步,如果成功把回调 resole 函数的参数作为结果
12 console.log(v);
13 }
14 demo();

返回promise 对象,失败状态

1 function say() {
2 return new Promise(function(resolve, reject) {
3 setTimeout(function() {
4 let age = 26
5 reject(`hello, joel,发生了异常。今年我 ${age} 岁`);
6 }, 1000);
7 });
8 }
9 async function demo() {
10 try {
11 const v = await say(); // 输出:hello, joel,发生了异常。今年我 26 岁 等待这个say 的异步,如果成功把回调 resole 函数的参数作为结果
12 console.log(v);
13 } catch (e) {
14 console.log(e)
15 }
16 }
17 demo();

async/await 相比原来的Promise的优势在于处理 then 链,不必把回调嵌套在then中,只要await 即可,如

1 function sing() {
2 return new Promise(function(resolve, reject) {
3 setTimeout(function() {
4 resolve(`来一首好听的歌吧~~~`);
5 }, 1000);
6 });
7 }
8 async function demo() {
9 try {
10 const v = await say();
11 const s = await sing();
12 console.log(v); // 输出:hello, joel。今年我 26 岁
13 console.log(s) // 来一首好听的歌吧~~~
14 } catch (e) {
15 console.log(e)
16 }
17 }
18 demo();

如果使用原来的Promise 就是把回调放在then()中。
总结
- async 告诉程序这是一个异步,awiat 会暂停执行async中的代码,等待await 表达式后面的结果,跳过async 函数,继续执行后面代码
- async 函数会返回一个Promise 对象,那么当 async 函数返回一个值时,Promise 的 resolve 方法会负责传递这个值;当 async 函数抛出异常时,Promise 的 reject 方法也会传递这个异常值
- await 操作符用于等待一个Promise 对象,并且返回 Promise 对象的处理结果(成功把resolve 函数参数作为await 表达式的值),如果等待的不是 Promise 对象,则用 Promise.resolve(xx) 转化
[转] js async await 终极异步解决方案的更多相关文章
- js async await 终极异步解决方案
既然有了promise 为什么还要有async await ? 当然是promise 也不是完美的异步解决方案,而 async await 的写法看起来更加简单且容易理解. 回顾 Promise Pr ...
- [.NET] 利用 async & await 的异步编程
利用 async & await 的异步编程 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/5922573.html 目录 异步编程的简介 异 ...
- [.NET] 利用 async & await 进行异步 IO 操作
利用 async & await 进行异步 IO 操作 [博主]反骨仔 [出处]http://www.cnblogs.com/liqingwen/p/6082673.html 序 上次,博主 ...
- 利用 async & await 的异步编程
走进异步编程的世界 - 开始接触 async/await 利用 async & await 的异步编程 async 的三大返回类型 公司技术需求备忘录
- async+await处理异步问题
在编写网页的时候我们常常会遇到异步问题,async+await是es6提出的解决异步的方法,下面我们来看看这个方法怎么实现解决异步的, 大家都知道,setTimeout是一个定时器.他是一个异步执行的 ...
- Atitit. Async await 优缺点 异步编程的原理and实现 java c# php
Atitit. Async await 优缺点 异步编程的原理and实现 java c# php 1. async & await的来源1 2. 异步编程history1 2.1. 线程池 2 ...
- 使用ES6新特性async await进行异步处理
我们往往在项目中会遇到这样的业务需求,就是首先先进行一个ajax请求,然后再进行下一个ajax请求,而下一个请求需要使用上一个请求得到的数据,请求少了还好说,如果多了,就要一层一层的嵌套,就好像有点c ...
- 深入理解协程(三):async/await实现异步协程
原创不易,转载请联系作者 深入理解协程分为三部分进行讲解: 协程的引入 yield from实现异步协程 async/await实现异步协程 本篇为深入理解协程系列文章的最后一篇. 从本篇你将了解到: ...
- NodeJs通过async/await处理异步
##场景 远古时代 我们在编写express后台,经常要有许多异步IO的处理.在远古时代,我们都是用chunk函数处理,也就是我们最熟悉的那种默认第一个参数是error的函数.我们来模拟一个Mongo ...
随机推荐
- Linux下virtualenv与virtualenvwrapper详解
在使用 Python 开发的过程中,工程一多,难免会碰到不同的工程依赖不同版本的库的问题: 亦或者是在开发过程中不想让物理环境里充斥各种各样的库,引发未来的依赖灾难. 此时,我们需要对于不同的工程使用 ...
- 设置 Jupyter notebook 工作空间 / 默认路径
常用的启动 Jupyter notebook 的两种方式是:命令行窗口启动和开始菜单启动.设置 Jupyter notebook 的默认路径也有两种常用方式: 修改配置文件 设置快捷方式. 1 通过修 ...
- mysql binlog空间维护
默认情况下,mysql主从同步的binlog日志,会一直保存. 对于如果已同步好的数据,这显然比较浪费资源. 且如果生产环境磁盘太小,随时还会爆掉,所以很有必要作好binlog的空间维护. 以下操作, ...
- django模板中的extends和include使用方法
一.extends使用方法 首先extends也就是继承,子类继承父类的一些特性.在django模板中通过继承可以减少重复代码. 首先我们建立一个app,名字叫做hello.别忘了在settings. ...
- flask实战-个人博客-编写博客前台
编写博客前台 博客前台需要开放给所有用户,这里包括显示文章列表.博客信息.文章内容和评论等功能功能. 分页显示文章列表 为了在主页显示文章列表,我们要先在渲染主页模板的index视图的数据库中获取所有 ...
- 《MySQL性能优化篇》阅读笔记
建表的时候,不要用null赋默认值,如:字符串的设置'',数据类型的设为0,不要将null设为默认值. 在MySQL中没有 full [outer] join,用union代替 各种 JOIN SQL ...
- django 解析上传xls文件
1.解析上传数据 class DataUploadAPIView(APIView): # authentication_classes = (JSONWebTokenAuthentication, S ...
- 第三章 linux常用的命令
安装笔记: 1 安装linux操作系统时,会默认创建一个超级管理员帐号:root 2 安装时,当进行到选择哪种类型的安装时,我们选择"使用所有空间"的类型 Linux概念性的东西 ...
- mysql Navicat通过代理链接数据库
1.做完host 账号 密码(数据库服务器)配置之后,选择ssh 2.配置代理服务器ip的登录的账号密码.(代理服务器必须可以连你的Navicat客户端和数据库服务器,不然怎么做代理.) 3.可以直接 ...
- requirements 操作
requirements作用描述: 很多 Python 项目中经常会包含一个 requirements.txt 文件,里面内容是项目的依赖包及其对应版本号的信息列表, 即项目依赖关系清单,其作用是用来 ...