axios.all扩展和捕获所有异常

13

我正在使用流行的库“axios”的.all方法来处理我的ajax请求。

但是如果所有请求都得到404错误,我该如何处理错误?

例如:

axios.all([
        axios.get('http://some_url'),
        axios.get('http://another_url'),
      ])
        .then(axios.spread((someUrl, anotherUrl) => {
         // ... boring stuff goes there
        }))
        .catch(() => {
         //... error goes there
        });

enter image description here

看起来只捕获了一个错误。

我该如何捕获所有错误?或者是否有一种 .finally 方法?

3个回答

11

问题(您已经知道)是,只要第一个Promise被拒绝,您就会进入 catch 块,从而无法在同一个 catch 中收集所有失败的响应。但是,您仍然可以手动处理失败的Promise以聚合错误,并在之后抛出。

请检查这是否适用于您:

const promises = [
  axios.get('http://some_url'),
  axios.get('http://another_url'),
]
const promisesResolved = promises.map(promise => promise.catch(error => ({ error })))

function checkFailed (then) {
  return function (responses) {
    const someFailed = responses.some(response => response.error)

    if (someFailed) {
      throw responses
    }

    return then(responses)
  }
}

axios.all(promisesResolved)
  .then(checkFailed(([someUrl, anotherUrl]) => {
    console.log('SUCCESS', someUrl, anotherUrl)
  }))
  .catch((err) => {
    console.log('FAIL', err)
  });

如果至少有一个promise失败,您将进入catch块。您可以通过检查响应的err数组来找到哪一个失败了。


1
对我来说可行,但代码并不那么直观易懂。你能否在promisesResolvedcheckFailed上添加更多解释呢? - Savitoj Cheema
@XavitojCheema,你只需要处理一些请求失败的情况。在这种情况下,你需要捕获它并从中返回 ({ error }),从而恢复异常。因此,想法是使所有请求都通过(解析),即使它失败了。如果有什么失败了,错误将作为响应对象的 error 属性可用。 - dfsq
好的,那需要更多了解 Promise 失败时的行为。感谢您的解释。 - Savitoj Cheema

1
由于Promise.all的快速失败行为,我认为这是不可能的。如果您的任何请求失败,它们将自动成为罪魁祸首,并在catch中返回结果。
    Promise.all([
      Promise.reject(Error('1')),
      Promise.reject(Error('2')),
      Promise.reject(Error('3'))
    ]).then((results) => {
      console.log(results)
    }, (error) => {
      console.log(error.message)
    })

这段代码的输出结果将始终为1,因为它是第一个失败的。我认为存储库上曾经有人请求类似的功能,但他们说这是不可能的。 我本来想把这个留作评论,但我的声望还不够高。

伙计,每个人在发布问题之前都要进行搜索。 https://github.com/axios/axios/issues/76#issuecomment-233146010 - WebArtisan
很有趣,上周我读了这篇文章,因为我也有同样的问题。应该直接贴链接。 - Charlie

0

@dfsq的解决方案对我没有用,因为当一个请求出错时,它会抛出所有请求。我修改了他的代码,使得每个请求都要么被解决,要么抛出错误。@dfsq请检查一下这个答案是否正确,因为我是在你的解决方案基础上构建的。

const promises = [
  axios.get('http://some_url'),
  axios.get('http://another_url'),
]
const promisesResolved = promises.map(promise => promise.catch(error => ({ error })))

function checkFailed (then) {
    return function (responses) {
        responses.forEach(response => {
            if (response.error)
                throw response;
            return then(response);
        })
    }
}

axios.all(promisesResolved)
  .then(checkFailed(response => {
    console.log('SUCCESS', response)
  }))
  .catch((err) => {
    console.log('FAIL', err)
  });

目前你的回答不够清晰,请[编辑]以添加更多细节,帮助其他人理解它如何回答问题。你可以在帮助中心找到有关如何编写好答案的更多信息。 - Albert Logic Einstein
@AlbertLogicEinstein,它已经写得很清楚了,请不要垃圾评论。如果您评论说它不清楚,请至少指出您不理解的部分,我会尝试用更简单的术语来解释给您听。此外,我的代码不是 OP 问题的 "答案",而是正确答案的替代升级。我遇到了需要这种功能的问题,所以如果有其他人需要,我分享了它。 - nevo_j

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接