Javascript 如何使用rxjs处理http并发请求和速率限制

Javascript 如何使用rxjs处理http并发请求和速率限制,javascript,node.js,rxjs,Javascript,Node.js,Rxjs,此应用程序需要向外部API发出100个HTTP请求。外部API受速率限制 下面是使用RXJS处理速率限制的工作解决方案,使用map操作符确定响应是否通知我们速率限制(在本例中为401),如果出现错误,还使用retryWhen延迟2秒并继续 但是,如果我们将代码从处理1个HTTP请求改为现在处理100个或更多HTTP请求,这是可行的。这个过程是按顺序处理的,对于我的usecase来说不够快 代码 const httpRequest = async () => { return axios

此应用程序需要向外部API发出100个HTTP请求。外部API受速率限制

下面是使用
RXJS
处理速率限制的工作解决方案,使用map操作符确定响应是否通知我们速率限制(在本例中为401),如果出现错误,还使用
retryWhen
延迟2秒并继续

但是,如果我们将代码从处理1个HTTP请求改为现在处理100个或更多HTTP请求,这是可行的。这个过程是按顺序处理的,对于我的
usecase
来说不够快

代码

const httpRequest = async () => {
  return axios("https://jsonplaceholder.typicode.com/todos/1")
}

export const httpRequestReactive = async () => {

    const $obserbable = defer(() => from(httpRequest()));

    const result = await $obserbable.pipe(
        map((res) => handleRateLimit(res)),
        retryWhen((errors) => errors.pipe(delay(2000), take(5))),
    ).toPromise();

    return result;

};


const handleRateLimit = (response) => {
    if (response.status === 401) {
        console.log("RATE LIMIT")
        throw response;
    }
    return response;
}

const main = async () => {

  const responseReactive = await httpRequestReactive()

  return responseReactive;

}



main().then((res) => {
  console.log("results: ", res)
}).catch((err) => {
  console.log("errors:: ", err)
})
我知道这个API能够在速率限制之前处理25个请求,然后我必须等待2秒钟。因此,我想一次批处理25个请求,这是我需要处理并发性的地方,类似于
Promise.all()

下面您可以看到我使用了
mergeAll
。它接受一个并发值。这似乎有效

代码(并发)

问题

  • [已解决]感谢@MoxxiManagarm:
    mergeAll
    而不是返回一个包含100个元素的结果数组,类似于
    Promise.all()
    我只剩下1个HTTP响应
  • 2。我不知道我的利率限制是否适用于
    mergeAll
    。我最初的代码假设是,如果一个单独的请求有速率限制,它应该重试该单个请求。但是,当我引入
    mergeAll
    时,如果一个请求的速率受限,是否会对批处理中的每个请求进行重试(这是我不希望发生的)。

    更新

    现在我有了一个响应数组,在进一步测试后,我可以看到im在数组中的响应比我预期的要多。例如,我留下了129条回复,我预计最多会有100条回复。这让我相信mergeAll和我的利率限制处理程序并没有按照我希望的方式工作。如果一个请求有速率限制,它会重试整个批中的所有请求吗

    我希望它在遇到速率受限的请求时暂停,重试单个请求,然后继续批处理中的其余请求。



    请查看下面的stackblitz(不幸的是,我找不到具有速率受限端点的伪/占位符api)

    只需在流的末尾添加
    toArray()
    操作符即可


    参见stackblitz:

    太好了,这确实给了我一系列的回应。我现在剩下的第二个问题是处理mergeAll的速率限制。
    export const httpRequestReactiveConcurrent = async () => {
    
        const payloads = new Array(100)​.fill({});
    
        const source$ = from(payloads​.map(x => defer(() => httpRequest()))); 
    
        const result = await source$.pipe(
            mergeAll(25),
            // tap((res) => console.log(res.status, res.headers)),
            map((res) => handleRateLimit(res)),
            retryWhen((errors) => errors.pipe(delay(1000), take(5))),
        ).toPromise();
    
    
        return result;
    
    
    };