• 【react hook】react hook组件中,在forEach中使用async/awati进行异步操作,为什么后面代码没有等待直接同步运行了呢?


    这是因为 forEach 方法不会等待 async/await 异步操作的完成。forEach 方法是一种同步的方法,它会在每个迭代内部同步执行一个回调函数。当遇到 await 时,会立即暂停执行,但是 forEach 方法不会等待回调函数中的 await 异步操作完成,而是立即执行下一个循环。

    举个例子,假如在 React Hook 组件中,我们想要通过遍历异步请求一个数组中的数据:

    import React, { useState, useEffect } from 'react';
    
    function MyComponent() {
      const [data, setData] = useState([]);
    
      useEffect(() => {
        const fetchData = async () => {
          const result = [];
          [1, 2, 3].forEach(async (num) => {
            const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${num}`);
            const data = await response.json();
            result.push(data);
          })
          setData(result);
        }
        fetchData();
      }, []);
    
      return (
        
      {data.map(item =>
    • {item.title}
    • )}
    ); }; export default MyComponent;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这个例子中,使用 forEach 方法来遍历并异步请求数据,然后将请求到的数据添加到 result 数组中。最后,将 result 数组通过 setData 设置为 data 的状态。然而,这个代码并不能达到我们的预期。

    原因是 forEach 方法是同步执行的,在执行的过程中会立即调用回调函数。在回调函数中使用 async/await 将请求转为异步操作,当执行到 await 时,虽然会暂停当前的执行,但是 forEach 会继续执行下一次循环,因此 result 数组没有等待所有的异步请求完成后再被更新,而是由于异步请求还没有完成,因此我们只得到了一个空的数组。

    解决这个问题的方法是使用 for..of 循环或者 Promise.all。在这里,我提供一个使用 Promise.all 的解决方案:

    Promise.all的写法

    import React, { useState, useEffect } from 'react';
    
    function MyComponent() {
      const [data, setData] = useState([]);
    
      useEffect(() => {
        const fetchData = async () => {
          const promises = [1, 2, 3].map(async (num) => {
            const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${num}`);
            return response.json();
          });
          const result = await Promise.all(promises);
          setData(result);
        }
        fetchData();
      }, []);
    
      return (
        
      {data.map(item =>
    • {item.title}
    • )}
    ); }; export default MyComponent;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    在这个例子中,我们将 forEach 方法替换为 map,用一个数组来保存返回的 Promise。然后,使用 Promise.all 来并行地等待所有的 Promise 被解决,并将它们的值传递给一个数组,然后使用 setData() 方法来更新组件状态。这样就可以达到我们的预期:异步请求完成后更新组件状态。

    for…of的写法

    使用 for...of 的方法和 forEach 的方法类似,也是使用异步函数进行请求。但是,在 for...of 循环体内部可以使用 await 等待异步操作的完成。例如:

    import React, { useState, useEffect } from 'react';
    
    function MyComponent() {
      const [data, setData] = useState([]);
    
      useEffect(() => {
        const fetchData = async () => {
          const result = [];
          for (const num of [1, 2, 3]) {
            const response = await fetch(`https://jsonplaceholder.typicode.com/todos/${num}`);
            const data = await response.json();
            result.push(data);
          }
          setData(result);
        }
        fetchData();
      }, []);
    
      return (
        
      {data.map(item =>
    • {item.title}
    • )}
    ); }; export default MyComponent;
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    在这个例子中,我们使用了 for...of 循环来遍历数组。在循环体内部使用 await 等待异步操作,这样可以保证每个异步操作在上一个异步操作完成后才会被执行。

    通过使用 for...of 来遍历数组,可以很好地保证每个异步操作能够按顺序被执行,并且可以等待每个异步操作的完成。这是相对于 forEach 来说的一种更为简洁的方式。

  • 相关阅读:
    由于找不到msvcp120.dll 无法继续执行怎么解决(最新方法分享)
    程序人生:从小公司到一线大厂,薪资翻倍,我做到了...
    OCCT示例学习笔记3--Modeling项目
    让开发回归简单模式-组件封装
    从Spring迁移到Spring Boot
    「入门篇」初识JVM (下下) - GC
    rust专集0(开篇)
    事务+事务并发+事务隔离级别【Interview Question】
    2022 ICPC 杭州站
    定时器及其应用
  • 原文地址:https://blog.csdn.net/hzxOnlineOk/article/details/134339821