【发布时间】:2017-10-17 23:54:38
【问题描述】:
我们有一个 Angular 2 站点,其中有一个 websocket 将数据从后端泵入我们的网格。为了指示最近的更新,我们使用 CSS 为受影响的单元格设置行的背景颜色和粗体字体。
指示应该只持续很短的时间。
1) 我们的第一次尝试是在下一批从服务器到达时重置所有指标。这运行良好,但在某些视图中很少更新,这意味着指标可以保持很长时间,这有点令人困惑。
如果更新指示器在固定间隔后消失,例如 4 秒,会更加一致。
2) 我们的下一个尝试是使用 CSS 动画。但过了一段时间,它就滞后了很多。给人的印象是,运行过多的动画会使浏览器过载,无法处理请求的时间。也许每个动画在后台都有自己的计时器?
3) 第三种尝试是让一个计时器以固定的时间间隔运行,然后检查要重置的记录。我们创建了一个 TimerService,它会定期检查到期项目。向计时器池添加项目时,可以配置任意等待时间。
这可行,但在日志窗口中经常出现违规警告:
[Violation] 'setInterval' handler took 56ms
[Violation] 'setInterval' handler took 74ms
[Violation] 'setInterval' handler took 63ms
[Violation] 'setInterval' handler took 88ms
...
但是当我们计算 checkItems 方法中发生的事情时,它只需要 0.03 毫秒!
我们都有 C# 背景,并且刚刚使用 Angular 工作了几个月。也许我们正在实施一种后端方法?
是否有我们错过的上下文切换?
还有其他更前端友好的方法吗?
我们可以对代码进行一些关键的优化吗?
感谢所有建议!
这是导致所有警告的建议 TimerService:
import { Injectable, OnInit } from "@angular/core";
import { Observable } from "rxjs/Rx";
import { Subject } from "rxjs/Subject";
@Injectable()
export class TimerService {
private timerItems: TimerItem[] = [];
private dueTimeReachedSubject: Subject<string> = new Subject<string>();
public dueTimeReached: Observable<string> = this.dueTimeReachedSubject.asObservable();
constructor() {
setInterval(() => this.checkItems(), 1000);
}
private checkItems() {
let now = Date.now();
let removeKeys: string[] = [];
this.timerItems.filter(t => t.dueTime <= now).forEach(t => {
this.dueTimeReachedSubject.next(t.key);
removeKeys.push(t.key);
});
this.timerItems = this.timerItems.filter(t => removeKeys.indexOf(t.key) < 0);
}
public add(key: string, delayInSeconds: number) {
let dueTime = Date.now() + delayInSeconds * 1000;
let timerItem = this.timerItems.find(t => t.key === key);
if (timerItem) {
timerItem.dueTime = dueTime;
}
else {
this.timerItems.push(new TimerItem(key, dueTime));
}
}
public remove(key: string) {
this.timerItems = this.timerItems.filter(t => t.key !== key);
}
}
class TimerItem {
constructor(public key: string, public dueTime: number) { }
}
编辑
我尝试使用 Observable.interval:相同的结果和完全相同的警告消息:“[Violation] 'setInterval' 处理程序花费了 xx 毫秒”
我尝试将 setTimeout 用于重复调用:结果相同,但警告消息已修改:“[Violation] 'setTimeout' 处理程序花费了 xx 毫秒”
我什至尝试清空每一行的 checkItems,但仍然收到警告。
警告是从 zone.js 中抛出的,似乎是 Angular 内部建议。我知道我可以在 Chrome 开发人员工具中关闭详细日志记录,但我经常将 console.debug 用于开发目的,这意味着它们也会消失。
我猜对于慢速函数来说,警告是可以的,但在这种情况下,它只是触发了一个 setInterval 函数。为什么会很慢?
【问题讨论】:
-
相当盲目的建议:如果你时间:
setInterval( () => { start; this.checkItems(); end; }, 1000);会发生什么?0.03 ms是一致的度量,当 Chrome 记录'setInterval' handler took 74ms时您也会观察到? -
你能在没有
@Injectable装饰器的情况下测试你的类吗? -
这不是一个通用的解决方案,但是您可以将一个类应用于一批行并使其一起淡出。它会节省很多计算
-
在这种情况下,如果进程由具有许多子组件的智能组件处理,您还应该使用
ChangeDetectionStrategy.OnPush -
Array.filter导致此问题,尝试基本的for循环,看看它是否持续
标签: javascript css node.js angular animation