zoukankan      html  css  js  c++  java
  • 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异步的发展就是让异步处理起来越来越像同步。

     
     
  • 相关阅读:
    origin/HEAD -> origin/master 这个分支是干嘛的啊
    使用Spring Boot来加速Java web项目的开发
    分辨真假数据科学家的20个问题及回答
    我的数学建模历程
    计算机科学中最重要的32个算法
    期权交易基本原理——买进看跌期权(Long Put),卖出看跌期权(Short Put)
    期货交易术语
    apecceosummit2016
    opencv 61篇
    server-pc--------------->lspci,lsusb,meminfo等配置信息
  • 原文地址:https://www.cnblogs.com/jyughynj/p/14429662.html
Copyright © 2011-2022 走看看