【问题标题】:Two looped async calls followed by a sync call两个循环的异步调用,然后是一个同步调用
【发布时间】:2023-03-05 09:21:01
【问题描述】:

我需要编辑以前保存的包含附件的邮件。在编辑功能中,用户应该能够编辑邮件标题或文本、替换现有附件或删除附件。

场景:用户对消息文本进行了更改,替换了一个附件并删除了 2 个附件并点击了保存。 OnClick 的 Save 按钮,需要发生以下动作

  1. 先异步替换和删除 API 调用
  2. 如果替换和删除成功,则调用 api 保存对文本的更改

这就是我所在的地方..

Promise.all 中的Promise.all 中的replacedelete 在循环promise 完成之前执行,导致外部promise(在handleSave 中)总是得到一个resolved 的promise。

deleteDatareplaceData 是包含要替换/删除的数据的数组

const delete = () => {
    if (deleteData.length > 0) {
      return Promise.all([
        deleteData.map(data => fetch(url)
          .then((response) => {
            if (!response.ok) {
              throw new Error('Delete Failed');
            }
          })
        ),
      ]).then(() => Promise.resolve('Deleted'));
    }
    return Promise.resolve('Nothing to delete');
  };

const replace = () => {
    if (replaceData.length > 0) {
      return Promise.all([
        replaceData.map(data => fetch(url)
          .then((response) => {
            if (response.status === 400) {
              response.text().then((error) => {
                const errorObject = JSON.parse(error);
                throw new Error(error);
              });
            } else if (!response.ok) {
              throw new Error('Update Failed');
            }
          })
        ),
      ]).then(() => Promise.resolve('Replaced'));
    }
    return Promise.resolve('Nothing to replace');
  };

const saveMessage = () => {
    fetch(saveUrl)
        .then((response) => {
            if (response.status === 400) {
              response.text().then((error) => {
                const errorObject = JSON.parse(error);
                throw new Error(error);
              });
            } else if (!response.ok) {
              throw new Error('Save Failed');
            }
        });
}

const handleSave = () => {
  Promise.all([replace, delete])
     .then(() => {
       saveMessage();
      }).catch((e) => {
        //Catch action
      })
  }

【问题讨论】:

  • 你的save 没有返回任何东西,你可能想要return fetch 调用,以便它可以在下面的handleSave 中被捕获

标签: javascript reactjs loops promise fetch


【解决方案1】:

对于您的Promise.alls,您当前正在传递一个包含单个项目的数组,其中该项目是一个 Promise 数组。因此,Promise.all 会立即解析。

将一组 Promise 传递给 Promise.all - 也就是说,只是 .map,而不是 [data.map(...)]。变化:

return Promise.all([
  deleteData.map(data => fetch(url)

return Promise.all(
  deleteData.map(data => fetch(url)

return Promise.all([
  replaceData.map(data => fetch(url)

return Promise.all(
  replaceData.map(data => fetch(url)

另外,在 replace 内部,当出现 400 错误时,它不会返回 inner .text Promise,因此它映射的 Promise.all 不会在您想要的时候拒绝。变化:

if (response.status === 400) {
  response.text().then((error) => {
    const errorObject = JSON.parse(error);
    throw new Error(error);
  });

if (response.status === 400) {
  return response.json().then((error) => {
    throw new Error(error);
  });

(注意你可以用.json()代替JSON.parse

此外,对于要在 catch 中处理的 saveMessage 错误,您也应该返回其每个 Promise:

const saveMessage = () => {
  return fetch(saveUrl)
    .then((response) => {
      if (response.status === 400) {
        return response.json().then((error) => {
          throw new Error(error);
        });
      } else if (!response.ok) {
        throw new Error('Save Failed');
      }
    });
};

【讨论】:

  • 谢谢,但这不是问题。问题是替换和删除中的循环没有按预期工作。我更喜欢保留 .text() 因为如果响应为空 .json() 失败
  • 这绝对是问题的至少一部分。你能说明你在哪里定义deleteDatareplaceDatareplacedelete吗?
  • deleteData 和 replaceData 是包含要替换/删除的数据的数组
  • 我看到了问题,您将数组数组传递给 Promise.all 而不是 Promises 数组。
  • 你确定你添加了return吗?也就是说,return response.text().json() 而不仅仅是 response.text().json()?
猜你喜欢
  • 1970-01-01
  • 2015-04-18
  • 1970-01-01
  • 2017-12-26
  • 1970-01-01
  • 2010-10-25
  • 2018-06-24
  • 2020-07-03
  • 2017-06-16
相关资源
最近更新 更多