• JS中按照顺序依次执行多个异步任务


    一、问题描述

    有很多个请求需要依次发送,待上一个请求完成之后再发送下一个请求,发生异常时也要能够继续后面的请求。

    二、思路

    一个请求完成之后再发送下一个请求,关键在于发送一个之后先停下来等待该请求完成,处理之后再继续下一个请求。生成器generator里面的yield语句可以分割代码,程序遇到yield会停住,通过next语句可以一次执行一个yield分割的语句,本文尝试使用生成器完成依次发送多个请求的功能。

    生成器示例如下:

     1 // 生成器通过函数名前加*创建
     2 function * generatorFn() {
     3     yield 1;
     4     yield 2;
     5 }
     6 // 调用生成器
     7 let g = generatorFn();
     8 // 通过next方法执行,返回yield后面的值,且整个生成器未执行完之前done为false
     9 console.info(g.next()); // {value: 1, done: false}
    10 console.info(g.next()); // {value: 2, done: false}
    11 // 执行完之后value为undefined,done为true
    12 console.info(g.next()); // {value: undefined, done: true}
    13 console.info(g.next()); // {value: undefined, done: true}

    三、步骤

    通过依次发送100个不同的请求来介绍,首先先把100个请求放入生成器内:

    1 let baseUrl = 'https://jsonplaceholder.typicode.com/todos/';
    2 function* generator() {
    3     for (let i = 1; i <= 100; i++) {
    4         yield fetch(baseUrl + i);
    5     }
    6 }

    接下来要先调用next()开始一个yield语句,让请求发送出去,然后处理好结果后再次调用next(),如此循环,知道next()返回done: true,通过递归实现如下:

     1 function run(res) {
     2     if (!res.done) {
     3         res.value
     4             .then((response) => response.json())
     5             .then((json) => {
     6                 console.log(json);
     7                 document.writeln('id: ' + json.id + '<br>');
     8                 run(gen.next());
     9             });
    10     }
    11 }
    12 
    13 // 开始执行
    14 let gen = generator();
    15 run(gen.next());
    可以观察到页面中会按照请求发送的顺序输出结果如下:

    完整代码如下:

     1 <!DOCTYPE html>
     2 <html lang="en">
     3     <head>
     4         <meta charset="UTF-8" />
     5         <meta name="viewport" content="width=device-width, initial-scale=1.0" />
     6         <title>fetch one by one</title>
     7         <script>
     8             // 构造100个请求
     9             let baseUrl = 'https://jsonplaceholder.typicode.com/todos/';
    10             function* generator() {
    11                 for (let i = 1; i <= 100; i++) {
    12                     yield fetch(baseUrl + i);
    13                     if (i == 4) { // 故意制造一个异常
    14                         yield fetch('fsfdsfsdf');
    15                     } else {
    16                         yield fetch(baseUrl + i);
    17                     }
    18                 }
    19             }
    20 
    21 
    22             // 处理请求结果并发送下一次请求
    23             function run(res) {
    24                 if (!res.done) {
    25                     res.value
    26                         .then((response) => response.json())
    27                         .then((json) => {
    28                             console.log(json);
    29                             document.writeln('id: ' + json.id + '<br>');
    30                             run(gen.next());
    31                         })
    32                         .catch((err) => { // 处理一下异常
    33                             console.info(err);
    34                             run(gen.next());
    35                         });
    36                 }
    37             }
    38             // 开始执行
    39             let gen = generator();
    40             run(gen.next());
    41         </script>
    42     </head>
    43     <body></body>
    44 </html>

    四、其他实现

    await会强制其他代码等待,直到后面的promise执行完毕,可以使用async和await完成类似功能:

     1 // 使用async和await
     2 let baseUrl = 'https://jsonplaceholder.typicode.com/todos/';
     3 async function ajax() {
     4     for (let i = 1; i <= 100; i++) {
     5         await fetch(baseUrl + i).then((response) => response.json())
     6             .then((json) => {
     7                 console.log(json);
     8                 document.writeln('id: ' + json.id + '<br>');
     9             })
    10             .catch((err) => { // 处理一下异常
    11                 console.info(err);
    12             });
    13     }
    14 }
    15 ajax();

    以上项目中需要依次发送异步请求的实现方法,JS异步的发展就是让异步处理起来越来越像同步。

     
     
  • 相关阅读:
    【Jdbc/Metadata】借助Metadata获得表字段的设定细节
    MASTER: Multiaspect nonlocal network for scene text recognition
    Centos8 中如何使用journalctl分析日志
    如何调试SSH连接
    如何将lvm卷移动到另一台服务器中
    CentOS8中恢复根目录为默认权限
    lightdb/postgresql中序列的使用以及oracle兼容计划
    PostgreSQL 15 Beta 1 发布
    PostgreSQL 14.3、13.7、12.11、11.16 和 10.21 发布
    MySQL/mariadb到LightDB开发迁移指南
  • 原文地址:https://www.cnblogs.com/jyughynj/p/14429662.html
Copyright © 2020-2023  润新知