angular - 我将如何使用 RXJS 实现“延迟执行计时器”
问题描述
我有一个用例,由于模板问题,Angular 的错误处理程序被 25 条以上的错误消息轰炸。由于我的自定义错误处理程序正在使用远程记录器 (sentry.io),因此应用程序因对 sentry.io 的 API 请求过多而变得无响应。
现在我使用“懒惰的计时器”方法解决了这个问题,如下所示:
import { ErrorHandler, Injectable } from '@angular/core';
import { LoggingService } from './sentry.provider';
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
private errorBuffer: Array<any>;
private lazyTimer: any;
constructor(private logger: LoggingService) {
this.errorBuffer = [];
};
handleError(error) {
this.errorBuffer.push(error);
this.processErrorBuffer();
};
private processErrorBuffer() {
if (this.lazyTimer) { clearTimeout(this.lazyTimer) };
this.lazyTimer = setTimeout(() => {
if (this.errorBuffer.length === 1) {
let error = this.errorBuffer.pop();
this.logger.reportError(error);
} else if (this.errorBuffer.length > 1) {
this.logger.reportError(this.errorBuffer);
this.errorBuffer = [];
};
}, 300)
};
}
所以基本上在每个错误之后而不是处理它我 setTimeout 它将执行错误处理逻辑或将被清除和更新(如果新错误在 300 毫秒内出现)。
这样,我可以将单个错误发送到 Sentry 或批处理(数组)。
我尝试使用 RXJS 实现相同的逻辑,但没有找到方法。我似乎无法理解哪个运营商执行这种计时器更新。
那么我需要使用哪个运算符来使用 RXJS 来复制这种行为?
解决方案
DebounceTime 描述(来自 RXJS 文档):
https://rxjs-dev.firebaseapp.com/api/operators/debounceTime
仅在经过特定时间跨度而没有另一个源发射后,才从源 Observable 发射一个值。
我怎么能看到,您在调用this.logger.reportError
函数后删除了所有错误,因此无需使用 ReplaySubject。
取决于您的功能逻辑,我以这种方式做到了。请检查示例。
import { ErrorHandler, Injectable } from '@angular/core';
import { LoggingService } from './sentry.provider';
import { debounceTime, scan } from 'rxjs/operators'
@Injectable()
export class GlobalErrorHandler implements ErrorHandler {
private errorListener = new Subject(); // <-- you need to import subject from RXJS
constructor(private logger: LoggingService) {
this.errorListener
.pipe(
// scan operator will collect all of the responses in one array
scan((acc, curr) => [...acc, curr], []),
// debounceTime operator will trigger event for the listeners only once when after the last action passed 400 ms
debounceTime(400)
).subscribe(errorBuffer => {
// errorBuffer is the collected errors list
this.processErrorBuffer(errorBuffer);
})
};
handleError(error) {
this.errorListener.next(error);
};
private processErrorBuffer(errorBuffer) {
if (errorBuffer.length === 1) {
this.logger.reportError(errorBuffer[0]);
} else if (this.errorBuffer.length > 1) {
this.logger.reportError(errorBuffer);
};
};
}
推荐阅读
- netlify-cms - Netlify CMS 和企业 Github 实例
- mysql - 我可以为 sql 命令声明参数类型吗?我无法插入布尔值,它被视为字符串
- firebase - 在创建新帐户时,屏幕一直在颤动
- vba - 访问 VBA - 使用组合框(多值字段)时类型不匹配
- javascript - 当我点击菜单中的 a 时关闭我的跨度
- android - ARCore – 呈现在我面前的 3d 对象
- python - 如何使用 Pandas 将数据写入 Excel 中的现有文件?
- reactjs - React Materials-UI 禁用处理程序中的按钮
- nginx - 如何让 Nginx HLS 应用程序根据请求拉取 RTMP
- blazor - 如何将 blazor 客户端/服务器应用程序发布到 linux Web 服务器?无权访问 ssh 并且 dotnet publish 不提供 index.html