使用 async / await, 搭配 promise, 可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性. 本文介绍 async / await 的基本用法和一些注意事项.

await

引用MDN的介绍:

await 操作符用于等待一个 Promise 对象, 它只能在异步函数 async function 内部使用.

await 的使用语法非常简单:

[return_value] = await expression;

其中 expression 是一个 Promise 对象或者任何要等待的值;

而 await expression 的执行结果有以下几种情况:

  1. 若 expression 是一个 Promise 对象, 并且其以值 x 被 fulfilled, 则返回值为 x.

  2. 若 expression 是一个 Promise 对象, 并且其以异常 e 被 rejected, 则抛出异常 e.

  3. 若 expression 不是 Promise 对象, 则会将 expression 处理成一个以 expression 值被 fulfilled 的 Promise 对象, 然后返回这个 Promise 对象的最终值 (即 expression 值). 这种用法没太大意义, 因此实际使用时还是尽量在 await 后跟一个 Promise 对象.

  4. 另外需要注意的是, await 在等待 Promise 对象时会导致 async function 暂停执行, 一直到 Promise 对象决议之后才会 async function 继续执行.

    通过一段代码来看一下:

async function foo() {
var a = await new Promise((resolve) => {
setTimeout(() => {
resolve(1);
}, 2000);
});
console.log(a); // 第2秒时输出: 1 try {
var b = await new Promise((resolve, reject) => {
setTimeout(() => {
reject(2);
}, 1000);
})
} catch (e) {
console.log(e); // 第3秒时输出: 2
} // 函数暂停2秒后再继续执行
var sleep = await new Promise((resolve) => {
setTimeout(() => {
resolve('sleep');
}, 2000);
}); var c = await 3;
console.log(c); // 第5秒时输出: 3
} foo();

  

async

使用 async function 可以定义一个 异步函数, 语法为:

async function name([param[, param[, ... param]]]) { statements }

async 函数的返回值很特殊: 不管在函数体内 return 了什么值, async 函数的实际返回值总是一个 Promise 对象. 详细讲就是:

若在 async 函数中 return 了一个值 x, 不管 x 值是什么类型, async 函数的实际返回值总是 Promise.resolve(x).

那么 Promise.resolve(x) 最终返回一个什么样的promise呢? 来看一下MDN的介绍:

Promise.resolve(value)方法返回一个以给定值解析后的Promise对象。但如果这个值是个thenable(即带有then方法),返回的promise会“跟随”这个thenable的对象,采用它的最终状态(指resolved/rejected/pending/settled);否则以该值为成功状态返回promise对象。

接下来看一段代码的应用. 假设有这样一个场景: 需要先通过 请求1 拿到 数据1, 然后通过通过 请求2 并携带发送 数据1 获取到 数据2, 拿到 数据2 之后再展示到页面.

方案一:

async function showData() {
// 假装请求数据1
var data1 = await new Promise((resolve) => {
setTimeout(() => {
resolve('data1');
}, 1000);
}); // 假装请求数据2且此请求依赖数据1
var data2 = await new Promise((resolve) => {
setTimeout(() => {
resolve('data2');
}, 1000);
}); // 展示数据2
console.log(data2);
} showData();

  

上面这段代码是依次获取到 数据1 和 数据2, 然后再展示 数据2.

既然 async 函数总是返回一个promise, 那么也可以在一个 async 函数返回获取 数据2 的promise, 调用函数后再使用 then方法拿到数据, 代码如下:

async function getData() {
// 假装请求数据1
var data1 = await new Promise((resolve) => {
setTimeout(() => {
resolve('data1');
}, 1000);
}); // 假装请求数据2且此请求依赖数据1
return new Promise((resolve) => {
setTimeout(() => {
resolve('data2');
}, 1000);
});
} getData().then((v) => {
console.log(v);
});

  转自:https://blog.csdn.net/juhaotian/article/details/78934097
https://segmentfault.com/a/1190000010244279

async/await的使用以及注意事项的更多相关文章

  1. async & await 异步编程的一点巧方法

    await 关键字不会创建新的线程,而是由Task任务或是FCL中的xxxAsync等方法创建的线程,而且这里创建的线程都是基于线程池创建的工作线程,属于后台线程. await关键字会阻塞/暂停调用它 ...

  2. async/await使用深入详解

    async和await作为异步模型代码编写的语法糖已经提供了一段时间不过一直没怎么用,由于最近需要在BeetleX webapi中集成对Task方法的支持,所以对async和await有了深入的了解和 ...

  3. Python 进阶 异步async/await

    一,前言 本文将会讲述Python 3.5之后出现的async/await的使用方法,我从上看到一篇不错的博客,自己对其进行了梳理.该文章原地址https://www.cnblogs.com/dhcn ...

  4. 异步编程之Async,Await和ConfigureAwait的关系

    在.NET Framework 4.5中,async / await关键字已添加到该版本中,简化多线程操作,以使异步编程更易于使用.为了最大化利用资源而不挂起UI,你应该尽可能地尝试使用异步编程.虽然 ...

  5. Async,Await和ConfigureAwait的关系

    [转自]https://mp.weixin.qq.com/s/h10V-FshGoaQUWFPfy-azg 在.NET Framework 4.5中,async / await关键字已添加到该版本中, ...

  6. 测试Promise与Async/await的基本使用

    想在项目中用, 发现自己不是很熟 promise基本使用 基本使用-思路 new Promise()返回了一个状态机 一个完全无法被外界影响的状态机 构造函数, 传入一个函数, 两个参数, 分别是re ...

  7. 异步编程新方式async/await

    一.前言 实际上对async/await并不是很陌生,早在阮大大的ES6教程里面就接触到了,但是一直处于理解并不熟练使用的状态,于是决定重新学习并且总结一下,写了这篇博文.如果文中有错误的地方还请各位 ...

  8. 温故知新,CSharp遇见异步编程(Async/Await),聊聊异步编程最佳做法

    什么是异步编程(Async/Await) Async/Await本质上是通过编译器实现的语法糖,它让我们能够轻松的写出简洁.易懂.易维护的异步代码. Async/Await是C# 5引入的关键字,用以 ...

  9. C#async\await组合

    一.概述 编译器提供的便捷功能,就是语法糖.我的理解是为了优化代码.被async修饰的函数被称之为异步函数,主要用于异步编程,着重于靠await实现回调机制. 二.声明 //async用在方法名之前 ...

随机推荐

  1. HTML前端入门归纳——控件

    本人一直在从事.net的开发,界面都是采用的WPF,近期花了一个多月进行HTML前端的学习,在这里呢进行学习总结和归纳. 本系列将主要分为4个模块: 控件 样式 布局 JavaScript 根据多年W ...

  2. gulp --watch直接退出,并没有监听

    1.在es6(彩票项目)搭建环境时遇到gulp --watch 只运行一次就退出了不能监听: D:\nodejs\es6-base>gulp --watch [::] Failed to loa ...

  3. 51nod1117【贪心】

    思路:哈夫曼树~~哇塞,那么有道理. 利用堆维护:每次从堆里取两个最小加起来,然后还是最小的两个,最后只剩一根总的 #include <bits/stdc++.h> using names ...

  4. 汇总各个部门当前员工的title类型的分配数目,结果给出部门编号dept_no、dept_name、其当前员工所有的title以及该类型title对应的数目count

    CREATE TABLE `departments` (`dept_no` char(4) NOT NULL,`dept_name` varchar(40) NOT NULL,PRIMARY KEY ...

  5. unite2017相关

    日程 http://unite2017.csdn.net/ http://www.sohu.com/a/137202360_280780 http://www.gameres.com/750046.h ...

  6. LeetCode.8-字符串转整数(String to Integer (atoi))

    这是悦乐书的第349次更新,第374篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Medium级别的第4题(顺位题号是8).实现将字符串转换为整数的atoi方法. 该函数首先去掉所需丢 ...

  7. day8文件操作作业详解

    1.day8题目 1,有如下文件,a1.txt,里面的内容为: 老男孩是最好的培训机构, 全心全意为学生服务, 只为学生未来,不为牟利. 我说的都是真的.哈哈 分别完成以下的功能: a,将原文件全部读 ...

  8. PAT甲级——1107 Social Clusters (并查集)

    本文同步发布在CSDN:https://blog.csdn.net/weixin_44385565/article/details/90409731 1107 Social Clusters (30  ...

  9. CC34:判断直线相交

    题目 解法 水题,判断斜率.判断截距,ok..... class CrossLine { public: bool checkCrossLine(double s1, double s2, doubl ...

  10. 桥接设计模式(Bridge)

    Bridge??? Bridge的意思是"桥梁".就像在现实世界中,桥梁的功能是将河流的两侧连接起来一样,Bridge模式的作用也是将两样东西连接起来,它们分别是类的功能层次结构和 ...