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异步的发展就是让异步处理起来越来越像同步。

 
 
原文地址:https://www.cnblogs.com/jyughynj/p/14429662.html