在这里与promise 搏斗...

我的用户发出需要在后端进行多个REST调用的单个请求.我将用户发出的每个请求和两个REST响应作为一个项存储在‘Records’数组中,如下所示:

[
  {
    call:userRequest,
    responses: [
        {
          source:source1
          response:responseText
        },
        {
          source:source2
          response:responseText
        }
      ]
  }
]

我使用map函数进行多个REST API调用.我使用‘setThisCall’方法处理每个响应,该方法将每个响应的详细信息添加到数组‘thisCall’.完成后,将‘thisCall’用作‘Records’数组中‘Responses’的值,该值被分配给‘thisCall’.

await Promise.all(urls.map(async url =>  {
  
  fetch(url, { 
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: messageBody
  })
  .then((response) => response.json())
  .then((data) => {
    setThisCall(prev => ([ //sets thisCall
      ...prev,
      {
        source: source,
        response: data.body
      }
    ]))
  })
})).then(()=>{
  console.log("now adding to records")
  setRecords(prev => ([ //sets records
    {
      call: requestText,
      reponses: thisCall
      },
      ...prev
    ]))
  })

我try 使用Promise.all()让map函数完成垃圾处理,处理响应,并使用‘THEN’将调用添加到下一个‘Record’项.

但最终的‘THEN’是在生成‘thisCall’之前触发的,从而导致‘Records’中的‘Response’值为空.

我如何让‘setRecords’在其余代码完成后发生?

推荐答案

Issue

UseState挂钩的setter函数本质上是异步的. 当调用setRecords时,thisCall可能还没有更新,这就是为什么您在records中看到一个空的response值.

Solution

每个fetch请求返回一个新的promise,在调用setThisCall之后解析.它将确保在setRecords之前完成所有setThisCall个.

await Promise.all(urls.map(url =>  
  // Return a new promise that resolves after setThisCall
  new Promise((resolve, reject) => {
    fetch(url, { 
      method: "POST",
      headers: {
        "Content-Type": "application/json"
      },
      body: messageBody
    })
    .then(response => response.json())
    .then(data => {
      // Update thisCall with the response data
      setThisCall(prev => ([ 
        ...prev,
        {
          source: source,
          response: data.body
        }
      ]));
      // Resolve the promise after setThisCall
      resolve();
    })
    .catch(reject);
  })
)).then(()=>{
  // Update records after all fetch requests have completed
  setRecords(prev => ([ 
    {
      call: requestText,
      responses: thisCall
    },
    ...prev
  ]))
});

Reactjs相关问答推荐

TypeError:b不是React.js中的函数错误

使用REACT-RUTER-V6和ZUSTANDreact 中的身份验证

为多租户SSO登录配置Azure AD应用程序

错误./src/TopScroll.js 31:21-31导出';(作为';随路由导入)在';Reaction-Router-Dom';中找不到

如何在整个应用程序中显示通用弹出窗口中的点击事件

左边框不在图表中显示

MERN,将动态列表中的元素插入数组

预期无限重新渲染但没有发生

标签文本删除了 MUI 概述的输入

如何优化 React 应用程序的性能?

如何到达类组件中的状态?

MUI TextField Select 菜单的最大高度

从服务器获取数据时未定义,错误非法调用

表单错误后 Ionic React 无法 Select 单选按钮

在 React 的父级中多次调用子级时从子级获取数据到父级

使用 Jest/React 测试库时,如何测试由 setInterval 函数创建的 DOM 更改?

如何向 surveyjs 调查添加多个结尾?

我刚刚部署了我的 Vite React 站点,但我的图标/图像没有部署

当状态改变时如何执行一些动作,但只针对第一次更新?

如何防止 mui x-date-picker 被截断?