首页 > 解决方案 > Javascript Promise.all 处理大量请求

问题描述

我有一个批量创建参与者功能,Promise.allSettled用于发送 100 个axios POST请求。后端是Express,前端是React。该请求是调用单个add new participant休息 API。我已将后端超时设置为 15 秒,使用connect-timeout. 前端是 10 秒超时。

我的问题是当我单击批量添加按钮时,会触发批量创建并且Promise.allSettled并发启动。但是,我无法在所有并发请求完成之前发送新请求。因为我在前端设置了超时,所以新的请求会被取消。

有没有办法,我仍然可以发出并发请求,但该请求不会停止其他新请求?

这是前端代码,createParticipant是 API 请求。

const PromiseArr = []
for (let i = 0; i < totalNumber; i++) {
    const participant = participantList[i]
    const participantNewDetail = {
        firstName: participant.firstName,
        lastName: participant.lastName,
        email: participant.email,
    }
    PromiseArr.push(
        createParticipant(participantNewDetail)
            .then((createParticipantResult) => {
                processedTask++
                processMessage = `Processing adding participant`
                dispatch({ type: ACTIVATE_PROCESS_PROCESSING, payload: { processedTask, processMessage } })
            })
            .catch((error) => {
                processedTask++
                processMessage = `Processing adding participant`
                dispatch({ type: ACTIVATE_PROCESS_PROCESSING, payload: { processedTask, processMessage } })
                throw new Error(
                    JSON.stringify({
                        status: "failed",
                        value: error.data.message ? error.data.message : error,
                    })
                )
            })
    )
}
const addParticipantResults = await Promise.allSettled(PromiseArr)

PromiseArr是长度为 100 的 Promise 数组。

是否有可能我可以将这个大请求拆分为小块承诺数组并发送到后端,并且在每个请求间隙内,我可以发送另一个新请求,例如retriveUserDetail

在此处输入图像描述

标签: javascriptreactjsexpressconcurrencypromise

解决方案


如果您一次向服务器发送 100 个请求,那么服务器将需要一段时间来处理。最好是找到一种方法将它们全部组合成一个请求或极少数请求。一些服务器 API 具有在一个请求中执行多个查询的有效方法。

如果你不能这样做,那么你可能应该一次最多发送 5-10 个,这样服务器就不会被要求处理太多的同时请求,这会导致你的额外请求到达行尾并且处理时间太长。这将允许您发送其他东西并在您在 100 块上分块时处理它们,而无需等待所有它们完成。

如果这是从浏览器完成的,您还有一些浏览器保护限制来处理浏览器拒绝一次向同一主机发送超过 N 个请求的情况。因此,如果您发送的更多,它会将它们排队并保留它们,直到一些先前的请求完成。这可以防止一个客户端大量压倒服务器,但也会创建一长串请求,任何新请求都必须结束。处理该问题的方法不是永远向同一主机发送少量请求,然后当您要发送新请求时该队列/行将很短。

您可以查看这些代码片段,它们可以让您一次处理 N 个数据数组,而不是一次处理所有数据。其中每一个都有略微不同的控制选项,因此您可以决定哪一个最适合您的问题。

mapConcurrent() - 同时处理一个不超过 N 个请求的数组

pMap() - 类似于具有更多参数检查的 mapConcurrent

rateLimitMap() - 处理最多 N 个 requestsPerSecond

runN() - 允许您在出错时继续处理

这些都替换了Promise.all()您用于迭代数据、启动所有请求并将 Promise 收集到数组中的任何代码。这些函数接受一个输入数据数组,一个要调用的函数,它传递了一个数据项,并且应该返回一个解析为该请求结果的承诺,并且它们返回一个解析为原始数组中的数据数组的承诺顺序(与 相同的返回值Promise.all())。


推荐阅读