javascript - 使用 RxJs 在 Angular 中按顺序执行一个后端调用并重试
问题描述
我有一些 Javascript 代码可以通过 API 调用从数据库中删除文档。文档之间存在内部依赖关系,因此删除可能会失败。因此代码将尝试在 5 轮中删除所有文档。
但是因为我在 Angular 上并且使用 RxJs 来完成所有其他任务,所以使用 RxJs 解决方案而不是 async/await 和 promises 会很好。我已经设法使用 concatMap 删除一轮,但是如何进行重试?
private async deleteDocuments(documents: IDocument[]) {
let retries = 5;
let remaining = [...documents];
while (remaining.length > 0 && retries > 0) {
remaining = await this.deleteDocumentsOneTry(remaining);
retries--;
}
}
private async deleteDocumentsOneTry(documents: IDocument[]) {
const remaining: IDocument[] = [];
for (const document of documents) {
const deleted = await this.deleteDocument(document);
if (deleted) {
this.documentsDeleted++; // For progress bar
} else {
remaining.push(document);
}
}
return remaining;
}
private deleteDocument(document: IDocument) {
console.log(`Delete document ${document.name}`);
return this.backend
.deleteDocuments(document.id)
.pipe(
map(() => true),
catchError(() => of(false))
)
.toPromise();
}
解决方案
考虑实现它,如下所示:
return from(documents).pipe(
mergeScan((failed: number, document: IDocument) => {
return that.backend.deleteDocuments(document.id).pipe(
tap(x => this.documentsDeleted++),
mapTo(failed),
catchError((error, source) => failed < 5 ? source.pipe(mapTo(++failed)) : throwError(error))
)
}, 0)
)
简化实现:
let retries = 5;
from(documents).pipe(
concatMap(doc => that.backend.deleteDocuments(doc.id).pipe(
catchError((error, source) => --retries > 0 ? source : throwError(error)),
))
).subscribe((x) => this.documentsDeleted++)
推荐阅读
- c# - 将多个 DotNet 可执行文件合并为一个可执行文件
- html - 变换比例在Firefox中产生不同的结果
- ios - 无法删除关键路径“Bounds”的观察者,因为它没有注册为观察者
- c - 如何像素化二进制 (P6) PPM 文件
- javascript - 如何在不向 JSX 树中添加组件的情况下创建 React 组件
- html - 悬停背景颜色未正确填充 CSS 网格
- python - TypeError: __init__() 接受 2 个位置参数,但 Python 3 给出了 3 个?
- spring-boot - 使用 Spring Fox 的 Spring Boot Swagger 实现无法启动 bean 'documentationPluginsBootstrapper'
- c# - 如何为 Mediatr INotificationHandler 的单元测试发送 Moq 通知
- unix - 用于打印给定 num 的数字总和的 shell 脚本。如果输入为负数,则将 Not a positive num 显示为 o/p