【问题标题】:Javascript Promise.allSettled with large amount number of requestsJavascript Promise.all 处理大量请求
【发布时间】:2021-08-21 04:32:32
【问题描述】:

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

我的问题是当我单击批量添加按钮时,会触发批量创建并且 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 是 Promise 数组,长度为 100。

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

【问题讨论】:

    标签: javascript reactjs express concurrency promise


    【解决方案1】:

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

    如果您不能这样做,那么您可能应该一次最多发送 5-10 个,这样服务器就不会被要求处理太多同时请求,这会导致您的额外请求结束生产线并且处理时间过长。这将允许您发送其他内容并在您处理 100 个内容时对其进行处理,而无需等待所有内容完成。

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

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

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

    pMap() - 类似于 mapConcurrent,但有更多参数检查

    rateLimitMap() - 最多处理 N 个 requestsPerSecond

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

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

    【讨论】:

    • 感谢您的解释。我没有将它们组合在一个请求中的原因是我有一个进度条,显示完成时每个请求的状态。所以我需要分开每个。我会检查你提到的内容。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-02-11
    • 2015-04-29
    • 2020-12-16
    • 2013-11-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多