【问题标题】:Promise.all and building axios requests inside async functionPromise.all 和在异步函数中构建 axios 请求
【发布时间】:2021-03-25 17:12:12
【问题描述】:

我正在循环数据以构建多个 axios 请求,并且在这个异步循环中等待一些数据。

当我这样做时,Promise.all 会在 .catch(errror => {}) 的其中一个请求引发错误之前解决,我故意提供了一个错误数据,因此请求会被捕获。

return new Promise((resolve) => {
    let requestArr = [];
    requestsData.forEach(async (data) => {
        let waitForThisData = await someFunction(data.id);
        requestArr.push(
            axios
             .post()
             .then((response) => {})
             .catch((error) => {})
        );
    });

    Promise.all(requestArr).then(() => {
        resolve(true);
    });
});

我正在用 3 个请求对此进行测试,其中 1 个将被捕获。当我添加断点时,Promise.all 在转到其中一个请求之前已经解析。

如果我删除等待代码,那么我会得到预期的输出,在Promise.all 解析之前先捕获触发器。

那么为什么 Promise.all 在其中一个请求完成之前解决(错误并去捕获)?

【问题讨论】:

  • 你的问题是“为什么Promise.allcatchforEach 循环内被触发之前解决”?你想要的行为是什么?
  • @codemonkey 对不起,是的。在我的问题中更清楚地说明了这一点。
  • 您是否只是想知道为什么,或者您是否真的想在Promise.all 解决之前找出一种方法来捕获错误?关于前者,我没有太多要提供的东西,但如果是后者,我可以建议一些更改,以使您的代码以有意义的方式运行。
  • 通过在上面的函数中包含控制台语句可能有助于发布您获得的输出,不确定我是否完全理解问题
  • @codemonkey 后者会很有帮助,谢谢。

标签: javascript promise async-await axios


【解决方案1】:

这将使您的Promise.all在循环内的catch之后解析,或者,实际上,在所有请求(成功或不成功)之后:

const axios = require('axios');

const someFunction = () => {
    return new Promise(resolve => {
        setTimeout(() => resolve('222'), 100)
    })
}

const requestsData = ['https://httpstat.us/200', 'https://httpstat.us/205', 'https://httpstat.us/306']
const requestArr = requestsData.map(async data => {
    let waitForThisData = await someFunction(data);
    return axios.post(data)
            .then(response => {})
            .catch(error => console.log(error.toString()))
});

Promise.all(requestArr).then(() => {
    console.log('resolved promise.all')
})

https://httpstat.us/306 会产生一个错误的调用。您可以尝试将其放在requestsData 数组中的任何位置。

【讨论】:

  • 谢谢,它成功了。但我看到的唯一区别是它现在使用地图,这有什么不同?
  • @crimson589 好问题。代码中的 Promise.all 实际上试图解析一个空数组。在您的 forEach 循环有机会将任何内容推入 requestArr 变量之前,它就已到达。难怪它会在您的任何 axios 调用之前解决。相比之下,map 在继续下一行之前使用从其函数返回的任何内容(在我们的例子中为承诺)填充 requestArr。这就是与众不同的地方。顺便说一句,Todd Skelton 在他的回答中也指出了这一点。
【解决方案2】:

据我所见,您正在异步向requestArr 推送承诺,因此如果您在数组被填充之前调用promise.all。当其中的承诺解决时,它就会解决。通过删除await,您可以快速将所有请求推送到requestArr

所以为了回答您的问题,它已解决,因为在您的错误承诺调用 requestArr.push() 之前,requestArr 中的所有请求都已解决。

您可以尝试使用自己的 async foreach 函数来更好地做到这一点。

async function asyncForEach(array, callback) {
  for (let index = 0; index < array.length; index++) {
    await callback(array[index], index, array);
  }
}

现在您可以在拨打Promise.all() 之前先await foreach

let requestArr = [];

await asyncForEach(requestsData, async (data) => {
    let waitForThisData = await someFunction(data.id);
    requestArr.push(
        axios
            .post()
            .then((response) => { })
            .catch((error) => { })
    );
});

Promise.all(requestArr).then(() => {
    resolve(true);
});

【讨论】:

  • 我明白了,在查看我的代码后,我现在可以看到它。在上面的示例中我没有包含一部分,实际上在 await 语句之前有一些验证。并非循环中的所有内容都将通过 await 语句,因此代码已通过循环中的所有内容,但其中一个仍在“等待”并且尚未在 Promise.all 执行时被推送到 requestArr
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-03-31
  • 2019-12-21
  • 2018-05-12
  • 2021-07-02
  • 2020-08-03
  • 2021-01-27
相关资源
最近更新 更多