node.js - 在重试时设置动态延迟

标签 node.js typescript rxjs delay retrywhen

是否可以在每次重试后动态设置延迟值。我这样尝试过,但它看起来很精简,它保留了初始设置的值。

imageController(epgData: EpgDataDTO[], showOrMovie: string){
    var retryAfterMilliSeconds = 1000;
    epgData.forEach( (data) => {
        this.getImagesFromMovieDB(data.title).pipe(
            retryWhen((error) => {
                return error.pipe(
                    mergeMap((error: any) => {
                            if(error.response.status === 429) {
                                const retryAfter = error.response.headers;
                                retryAfterMilliSeconds = +retryAfter['retry-after'] * 1000
                                console.log(retryAfterMilliSeconds); // it tells me the correct value here but the retry happens every 1000ms
                                console.log(data.title);
                            }else{
                                this.errorHandling(error)
                                return of("error");
                            }
                            return of("error");
                        }),
                    delay(retryAfterMilliSeconds),
                    take(5)
                )
        }))
        .subscribe( (res) => {
            console.log(res.status);
            console.log(res.headers);

        });
    })
}

最佳答案

你已经非常接近了!为了让它工作,我所要做的就是将延迟(retryAfterMilliSeconds)移动到mergeMap()运算符的返回值之后,以将其绑定(bind)到相同的可观察值。如果没有这个,它会随机延迟 mergeMap() 的 RETURN,这对于 Observable 实际延迟来说是随机的。

我把它放在 Stackblitz 中来测试它。单击最右侧框架底部的“控制台”即可查看结果。

这是 StackBlitz 中的函数:

imageController(epgData: EpgDataDTO[], showOrMovie: string){
    var retryAfterMilliSeconds = 1000;
    epgData.forEach( (data) => {
        this.getImagesFromMovieDB(data.title).pipe(
            retryWhen((error) => {
                return error.pipe(
                    mergeMap((error: any) => {
                            if(error.response.status === 429) {
                                const retryAfter = error.response.headers;
                                retryAfterMilliSeconds = +retryAfter['retry-after'] * 1000
                                console.log(retryAfterMilliSeconds); // it tells me the correct value here but the retry happens every 1000ms
                                console.log(data.title);
                            }else{
                                this.errorHandling(error)
                                // return of("error"); <-- unnecessary since this will be executed with next statement
                            }
                            return of("error").pipe(delay(retryAfterMilliSeconds));
                        }),
                    // delay(retryAfterMilliSeconds),
                    take(5)
                )
        }))
        .subscribe( 
            (res) => {
                // console.log(res.status);
                // console.log(res.headers);
                const elapsedTime = Math.round(((new Date()).getTime() - startTime) / 1000);
                console.log(`'${res.status}' is Ok - total elapsed time ${elapsedTime} seconds`);
            }
        );
    })
}

其他一些注意事项:

  • getImagesFromMovieDB() 的返回实际上很重要 - 它需要为每次调用返回一个唯一的可观察值才能正常工作,请确保情况确实如此。我通过使用 delay 构造 Observable 返回,在 StackBlitz 中模拟了这一点。
  • 如您所见,我更改了 .subscribe() 中的第一个函数,以打印出获取此 res.status 的有效数据所花费的总时间。我这样做只是为了表明每次发射它正确地获取了所有延迟的总和。 每次失败后都会重试一段随机时间(我任意选择 5 到 10 秒),由原始函数中的响应 header 返回。
  • 次要观点:mergeMap 有两个返回 return of("error") 但第一个是不必要的,因为第二个将立即执行,所以我将其中一个注释掉了。

我希望这会有所帮助。

关于node.js - 在重试时设置动态延迟,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54027303/

相关文章:

typescript - 为什么 Typescript 不让 BehaviorSubject 采用联合类型?

javascript - Rxjs: block 和延迟流?

javascript - 无法从 socket.io 中的 Express 路由发出事件

typescript 否定类型检查

node.js - JadeJS 和重新渲染 View 时预先写入的表单值

generics - Typescript 泛型是否使用类型删除来实现泛型?

typescript - 如何键入以防止 Typescript 中的返回值

angular - 如何在 Angular 的可观察 map 中返回可观察对象

node.js - Winston 登录控制台但不在日志文件中

node.js - Node.js 基准测试