ECMAScript7 async/await 异步解决方案

Unsplash

Async 函数作为异步解决方案的最优解,async/await 特性能让我们编写出相比回调地狱和 Promise 链式调用更直观、更容易理解的代码,Async 函数返回一个 Promise 对象,可以使用 then() 方法添加回调函数,当函数执行的时候,一旦遇到 await 就会先返回,等到异步操作完成,再接着执行函数体内后面的语句

01 初识 async/await

const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url),
          data    = await request.json(); 
    console.log(`bookname: ${data.notebooks[4].name}`);
}
JianShuRequest('b0c7095032f3')

运行结果

02 将 Async 函数用在 Promise 链中

const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
JianShuRequest('b0c7095032f3').then(data => {
    console.log(`bookname: ${data.notebooks[4].name}`);
})

运行结果

03 使用 await 进行调用

const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
(async () => {
    const data = await JianShuRequest('b0c7095032f3');
    console.log(`bookname: ${data.notebooks[4].name}`);
})()
const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
var bookname = async () => {
    const data = await JianShuRequest('b0c7095032f3');
    console.log(`bookname: ${data.notebooks[4].name}`);
}
bookname()

运行结果

04 await 并行

通过移动 await 关键词的位置实现多个 await 操作串行或者并行

const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
var bookname = async () => {
    console.time('time');
    const data_1 = await JianShuRequest('b0c7095032f3');
    const data_2 = await JianShuRequest('b0c7095032f3');
    console.log(`bookname: ${data_1.notebooks[2].name}`);
    console.log(`bookname: ${data_2.notebooks[4].name}`);
    console.timeEnd('time');
}
bookname()

运行结果

const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
var bookname = async () => {
    console.time('time');
    const dataPromise_1 = JianShuRequest('b0c7095032f3');
    const dataPromise_2 = JianShuRequest('b0c7095032f3');
    const data_1 = await dataPromise_1;
    const data_2 = await dataPromise_2;
    console.log(`bookname: ${data_1.notebooks[2].name}`);
    console.log(`bookname: ${data_2.notebooks[4].name}`);
    console.timeEnd('time');
}
bookname()

运行结果

根据两种方式得到的数据对比,并行所运行的时间更短,其主要思路是,先触发所有的请求,得到 Promise 对象,再通过 await 等待 resolve 返回的结果

05 使用 try catch 捕捉错误

const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    if(request.status != 200) {
        throw new Error(request.statusText);
    }
    return await request.json();
}
const showJianShuRequest = async (id) => {
    try {
        const data = await JianShuRequest(id);
        console.log(`bookname: ${data.notebooks[4].name}`);
    }catch (err) {
        console.error(err);
    }
}
showJianShuRequest('666666');

运行结果

06 使用 Promise.all() 实现多个异步操作的并行

const fetch = require('node-fetch');
async function JianShuRequest(id) {
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
const showJianShuRequest = async () => {
    const [data_1, data_2] = await Promise.all([
        JianShuRequest('b0c7095032f3'),
        JianShuRequest('b0c7095032f3'),
    ])
    console.log(`bookname_1: ${data_1.notebooks[2].name}`);
    console.log(`bookname_2: ${data_2.notebooks[4].name}`);
}
showJianShuRequest();

运行结果

07 在循环中正确使用 await

const fetch    = require('node-fetch'),
      bluebird = require('bluebird');
async function JianShuRequest(id) {
    await bluebird.delay(1000);
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
const showJianShuRequest = async () => {
    console.time('time');
    const names = ['b0c7095032f3', 'b0c7095032f3'];
    for(const name of names){
        const data = await JianShuRequest(name);
        console.log(`bookname_1: ${data.notebooks[2].name}`);
        console.log(`bookname_2: ${data.notebooks[4].name}`);
    }
    console.timeEnd('time');
}
showJianShuRequest();

运行结果

const fetch    = require('node-fetch'),
      bluebird = require('bluebird');
async function JianShuRequest(id) {
    await bluebird.delay(1000);
    const url     = `https://www.jianshu.com/users/b0c7095032f3/collections_and_notebooks?slug=${id}`,
          request = await fetch(url);
    return await request.json();
}
const showJianShuRequest = async () => {
    console.time('time');
    const names = ['b0c7095032f3', 'b0c7095032f3'];
    const promises = names.map(x => JianShuRequest(x))
    for (const promise of promises) {
        const data = await promise;
        console.log(`bookname_1: ${data.notebooks[2].name}`);
        console.log(`bookname_2: ${data.notebooks[4].name}`);
    }
    console.timeEnd('time');
}
showJianShuRequest();

运行结果

参考资料 ECMAScript 6 入门——async 函数 玩转异步 JS :async/await 简明教程 三分钟学会用ES7中的Async/Await进行异步编程

本篇的内容到这里就全部结束了,源码我已经发到了 GitHub async-await 上了,有需要的同学可自行下载

End of File

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏大内老A

ASP.NET Core的配置(4):多样性的配置来源[中篇]

我们在本篇文章中会介绍三种针对物理文件的ConfiguationProvider,它们分别是针对JSON文件的JsonConfiguationProvider,...

21280
来自专栏步履前行

Java多线程--对象的可见性

  最近在看《Java并发编程实战》,并发方面的知识,今天看到了对象的可见性,在这里分享一下。

33940
来自专栏Linyb极客之路

对象共享:Java并发环境中的烦心事

并发的意义在于多线程协作完成某项任务,而线程的协作就不可避免地需要共享数据。今天我们就来讨论下如何发布和共享类对象,使其可以被多个线程安全地访问。

14840
来自专栏nnngu

百度搜索 “Java面试题” 前200页(面试必看)

本文中的题目来源于网上的一篇文章《百度搜索 “Java面试题” 前200页》,但该文章里面只有题目,没有答案。因此,我整理了一些答案发布于本文。本文整理答案的原...

862110
来自专栏Java成神之路

Spring_总结_04_高级配置(五)_运行时注入值

当讨论依赖注入的时候,我们通常所讨论的是将一个bean引用注入到另一个bean的属性或者构造参数中。它通常指的是将一个对象与另一个对象进行关联。

12420
来自专栏一名合格java开发的自我修养

spring常用注解使用解析

spring没有采用约定优于配置的策略,spring要求显示指定搜索哪些路径下的Java文件。spring将会把合适的java类全部注册成spring Bean...

8710
来自专栏蓝天

RPC的实现

RPC全称为Remote Procedure Call,即远过程调用。如果没有RPC,那么跨机器间的进程通讯通常得采用消息,这会降低开发效率,也会增加网络...

25730
来自专栏编程

如何修改动态代理的私有变量

最近在写一个 Spring Controller 的 JUnit 单元测试时,需要将一个Mock对象塞入到Controller的私有成员变量中,发现怎么都塞不成...

21590
来自专栏BinarySec

unexploitable Writeup[pwnable.tw]

最近在刷pwnable.tw(类似pwnable.kr,不过是台湾的)的题,看到了一个unexploitable的题目。根据题目描述:

30220
来自专栏Albert陈凯

2018-04-06 JDK 新特性总览

JDK5新特性 自动装箱与拆箱 枚举 静态导入 可变参数(Varargs) 内省(introspector) 泛型(Generic) For-Eac...

33840

扫码关注云+社区

领取腾讯云代金券