How to execute Promise.all only after an array of API calls finishes and catch the error if one of them fails?

huangapple go评论53阅读模式
英文:

How to execute Promise.all only after an array of API calls finishes and catch the error if one of them fails?

问题

我正尝试实现一个Redux操作,该操作迭代一个项目数组,并针对每个项目进行API调用;我想要的是仅在成功发送数组的所有项目之后设置成功状态。但如果其中一个失败,我希望它进入catch块并设置失败状态。

目前的情况是,在Promise.all内的setOpenAccountSuccess在所有项目都发送之前就已经运行了,即使其中一个失败也是如此。

我需要做什么更改才能使其正常工作?提前感谢您的帮助。以下是我拥有的代码:

export const openAccounts = (data, userId, addressId) => async (dispatch) => {
  dispatch(AccountsReducer.setOpenAccountsLoading());

  try {

    const openAccountsPromise = data.selectedProducts.map(async product => {
      let formatedData = setOpenAccountAndProductData(data, userId, addressId, product);

      await AccountsService.openAccounts(formatedData);
    });

    Promise.all(openAccountsPromise).then(dispatch(AccountsReducer.setOpenAccountSuccess()));

  } catch(error) {
    dispatch(AccountsReducer.setOpenAccountFailure(error.response?.data));
  }

}
英文:

I am trying to implement a redux action that iterates an array of items making an API call for each; what I want is to set the success state only after all the items of the array have been successfully sent. But if one of them fails I want it to go to the catch and set the failure state instead.

What is happening now is that the setOpenAccountSuccess inside the Promise.all is run even before all the items are sent and even if one of them fails.

What would I need to change to make it work? Thanks in advance. Here is the code I have:

export const openAccounts = (data, userId, addressId) => async (dispatch) => {
  dispatch(AccountsReducer.setOpenAccountsLoading());

  try {

    const openAccountsPromise = data.selectedProducts.map(async product => {
      let formatedData = setOpenAccountAndProductData(data, userId, addressId, product);

      await AccountsService.openAccounts(formatedData);
    });

    Promise.all(openAccountsPromise).then(dispatch(AccountsReducer.setOpenAccountSuccess()));

  } catch(error) {
    dispatch(AccountsReducer.setOpenAccountFailure(error.response?.data));
  }

}

答案1

得分: 1

确保在map循环中返回AccountsService.openAccountsPromise以收集所有的Promise值。

然后等待Promise.all(openAccountsPromise)的调用。由于循环和Promise.all都在同一个try / catch作用域中,任何失败的Promise将会在catch块中捕获。

export const openAccounts = (data, userId, addressId) => async (dispatch) => {
  dispatch(AccountsReducer.setOpenAccountsLoading());

  try {
    const openAccountsPromise = data.selectedProducts.map(product => {
      let formatedData = setOpenAccountAndProductData(data, userId, addressId, product);
      return AccountsService.openAccounts(formatedData);
    });
    
    await Promise.all(openAccountsPromise);
    dispatch(AccountsReducer.setOpenAccountSuccess();

  } catch(error) {
    dispatch(AccountsReducer.setOpenAccountFailure(error.response?.data));
  }
}
英文:

Make sure you return the Promise from AccountsService.openAccounts in the map loop to collect all of the promise values.

Then await the Promise.all(openAccountsPromise) call. Since both the loop and the Promise.all are in the same try / catch scope, any of the failed promises will be caught in the catch block.

export const openAccounts = (data, userId, addressId) => async (dispatch) => {
  dispatch(AccountsReducer.setOpenAccountsLoading());

  try {
    const openAccountsPromise = data.selectedProducts.map(product => {
      let formatedData = setOpenAccountAndProductData(data, userId, addressId, product);
      return AccountsService.openAccounts(formatedData);
    });
    
    await Promise.all(openAccountsPromise);
    dispatch(AccountsReducer.setOpenAccountSuccess();

  } catch(error) {
    dispatch(AccountsReducer.setOpenAccountFailure(error.response?.data));
  }
}

huangapple
  • 本文由 发表于 2023年7月7日 05:20:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/76632586.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定