在 react 中与 Promise.all 同时执行请求,将 promise 推送到数组

Doing requests concurrently with Promise.all pushing promises to an array in react

提问人:Joaquin Leimeter 提问时间:11/8/2023 最后编辑:Joaquin Leimeter 更新时间:11/10/2023 访问量:34

问:

我知道这是一个很长的标题,但它总结了我打算做什么。在某个应用程序中,我有一个表单,其中包含许多不同的部分,这些部分对 API 执行 POST 或 PATCH 请求。问题在于,在确认更改时,这些调用是立即执行的,而不是同时执行的。

我最想解决的解决方案是将 promise 添加到数组中,并使用 Promise.all 执行它们。

我在 React 中有一个带有父子组件的工作演示。如果父级持有 promise 状态数组,则子级推送 promise,父级执行 Promise.all。

Github pages demo
Repo - 分支

父母。

import { useEffect, useState } from "react";
import Child from "./child";

function Parent() {
  console.log("parent render");
  const [array, setArray] = useState<Array<() => Promise<unknown>>>([]);

  useEffect(() => {
    console.log("array in parent", array);
  }, [array]);

  const runPromises = () => {
    // Invoke each function to get the promise
    const promises = array.map((func) => func());

    // Execute the all promises concurrently
    Promise.all(promises)
      .then((values) => {
        console.log(values);
      })
      .catch((error) => {
        console.error(error);
      });
  };

  return (
    <>
      <div>Parent</div>
      <Child array={array} setArray={setArray} />
      <button onClick={runPromises}>Run promises</button>
    </>
  );
}

export default Parent;

孩子。

import { Dispatch, useEffect, useState } from "react";

type Props = {
  array: Array<unknown>;
  setArray: Dispatch<React.SetStateAction<unknown>>;
};

function Child({ array, setArray }: Props) {
  console.log("child render");
  const [count, setCount] = useState(0);
  count;

  useEffect(() => {
    console.log("array in child", array);
  }, [array]);

  const addToPromiseArray = () => {
    setCount((oldValue) => oldValue + 1);

    // Function that returns a promise when executed. This is done because fetching is eager when handled inside a new Promise constructor.
    const newPromise = () =>
      // new Promise created to fetch an API.
      new Promise((resolve, reject) => {
        fetch("https://picsum.photos/200/300")
          .then((response) => {
            if (response.ok) {
              resolve(response); // Resolving the Promise with the response
            } else {
              reject("Error fetching data"); // Reject the Promise in case of an error
            }
          })
          .catch((error) => {
            reject(error); // Reject the Promise in case of an error
          });
      });

    // Push the new Promise to the promises array to execute them in the parent component.
    setArray((oldValue) => [
      ...oldValue,
      newPromise, // Adding the resolved promise to the array
    ]);
  };

  return (
    <>
      <div>Child</div>
      <button onClick={addToPromiseArray}>Push to array</button>
    </>
  );
}

export default Child;

在代码中,您将找到解释所执行的每个操作的注释。相关组件位于 src/components/Parent.tsxsrc/components/Child.tsx

我想就这是否是一个很好的解决方案发表意见。我设法推送了 promise 并执行它们,方法是将它们包装在另一个函数中,该函数在子组件中返回 prmise,然后执行函数的 for 循环,获取 promise 并在事后使用 Promise.all 运行它们。这看起来很奇怪,但这是我找到的唯一方法。也许有更多经验的人可以提供帮助。感谢您抽出时间接受采访。

JavaScript ReactJS 异步 承诺

评论

2赞 Nate Norris 11/8/2023
这是一个非常常见的模式;我认为你走在正确的轨道上。如果您有很多 promise 想要同时解决,那么使用 Promise.all() 是您的不二之选。
0赞 Bergi 11/8/2023
将相关代码作为问题的一部分发布,而不是指向它的链接(这会腐烂 - 它甚至没有链接特定的提交,因此存储库内容可能会更改)。
0赞 Bergi 11/8/2023
承诺不会被“执行”。调用函数时会立即发出请求,并且循环中的所有请求仍会立即发出。这样做只是为了允许等待并发请求的所有结果。Promise.all
0赞 Joaquin Leimeter 11/8/2023
@Bergi 我将在今天晚些时候发布代码。感谢您的回复。
0赞 Bergi 11/11/2023
我想你的代码工作正常,作为一种模式还可以,但你的术语和变量名称是关闭的。你有一个函数数组,而不是一个承诺数组。所以它应该不是 ,也不是 ,并且对注释进行了很多更改。还要避免 Promise 构造函数的反模式,并且不要使用 单独的状态,而只是做 。runFuncsrunPromisesconst newFunctionconst newPromisefetchcountconst count = array.length

答: 暂无答案