使用 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. display:block inline-block inlined的区别

    一.首先要了解什么是块级元素与行级元素 块级元素 会占领页面的一行,其后多个block元素自动换行. 可以设置width,height,设置了width后同样也占领一行.同样也可以设置   margi ...

  2. Solr highlight

    hl.preserveMulti 默认是false.Set to true to perform highlighting on all values of a multivalued field a ...

  3. poj1144 tarjan求割点

    poj1144 tarjan求割点 额,算法没什么好说的,只是这道题的读入非常恶心. 注意,当前点x是否是割点,与low[x]无关,只和low[son]和dfn[x]有关. 还有,默代码的时候记住分目 ...

  4. 洛谷P2868 [USACO07DEC]观光奶牛Sightseeing Cows

    P2868 [USACO07DEC]观光奶牛Sightseeing Cows 题目描述 Farmer John has decided to reward his cows for their har ...

  5. 洛谷P1587 [NOI2016]循环之美

    传送门 不会,先坑着 https://kelin.blog.luogu.org/solution-p1587 //minamoto #include<cstdio> #include< ...

  6. Nacos深入浅出(八)

    Nacos-spring-context.java 感觉这个后台要比之前的Nacos复杂多了,涉及到很多基础的概念,慢慢看,这个后面慢慢更新解析过程 看到他的目录结构一个是基于注解,一个是XML的解析 ...

  7. Core 事件总

    NET Core 事件总线,分布式事务解决方案:CAP 背景 相信前面几篇关于微服务的文章也介绍了那么多了,在构建微服务的过程中确实需要这么一个东西,即便不是在构建微服务,那么在构建分布式应用的过程中 ...

  8. 如何给数组用fill函数和memset函数给数组赋初值

    fill是按照单元来赋值的,所以可以填充一个区间的任意值 #include<iostream> #include<stdio.h> #include<string.h&g ...

  9. Codeforces Round #377 (Div. 2) E. Sockets

    http://codeforces.com/contest/732/problem/E 题目说得很清楚,每个电脑去插一个插座,然后要刚好的,电脑的power和sockets的值相同才行. 如果不同,还 ...

  10. 【干货分享】大话团队的GIT分支策略进化史

    封面 作为一名85后的技术男,一转眼10年过去了(一不小心暴露了年龄,虽然我叫18岁fantasy),亲手写代码已经是5年前了,目前主要负责公司的软件产品的规划和设计(所以最近写的东西也主要与设计和产 ...