检查后,表达式已更改。以前的值:"几秒钟前"。当前值:'1 minute ago'实现自定义 TimeAgo 管道



我一直在尝试实现一些管道(angular 13),以便能够像twitter或其他web平台一样显示日期,而不是显示日期,我显示的是这样的消息:"1天前", "几秒钟前"…

我试图使用https://www.npmjs.com/package/ngx-pipes,但相同的问题与表达式已经改变后,它被检查显示相同。

我有一个通过signalr接收大量数据变化的表。我可以用ngx-pipe timeAgo代码的基础来创建一个自定义的timeAgo管道。

该管道的原始代码是(我复制来创建自定义管道的代码)

import { ChangeDetectorRef, NgZone, OnDestroy, Pipe, PipeTransform } from "@angular/core";

@Pipe({
name: "dateAgo",
pure: false
})
export class DateAgoPipe implements PipeTransform, OnDestroy {
changeDetectorRef: ChangeDetectorRef;
ngZone: NgZone;
timer: any;
constructor(changeDetectorRef: ChangeDetectorRef, ngZone: NgZone) {
this.changeDetectorRef = changeDetectorRef;
this.ngZone = ngZone;
}
ngOnDestroy() {
this.removeTimer();
}
transform(value: any, args?: any): any {
this.removeTimer();
const d = new Date(value);
const now = new Date();
const seconds = Math.round(Math.abs((now.getTime() - d.getTime()) / 1000));
const timeToUpdate = (Number.isNaN(seconds)) ? 1000 : this.getSecondsUntilUpdate(seconds) * 1000;
this.timer = this.ngZone.runOutsideAngular(() => {
if (typeof window !== 'undefined') {
return window.setTimeout(() => {
this.ngZone.run(() => this.changeDetectorRef.markForCheck());
}, timeToUpdate);
}
return null;
});
const minutes = Math.round(Math.abs(seconds / 60));
const hours = Math.round(Math.abs(minutes / 60));
const days = Math.round(Math.abs(hours / 24));
const months = Math.round(Math.abs(days / 30.416));
const years = Math.round(Math.abs(days / 365));
if (Number.isNaN(seconds)) {
return '';
} else if (seconds <= 45) {
return 'a few seconds ago';
} else if (seconds <= 90) {
return '1 minute ago';
} else if (minutes <= 45) {
return minutes + ' minutes ago';
} else if (minutes <= 90) {
return 'an hour ago';
} else if (hours <= 22) {
return hours + ' hours ago';
} else if (hours <= 36) {
return 'a day ago';
} else if (days <= 25) {
return days + ' days ago';
} else if (days <= 45) {
return 'a month ago';
} else if (days <= 345) {
return months + ' months ago';
} else if (days <= 545) {
return 'a year ago';
} else {
// (days > 545)
return years + ' years ago';
}
}
removeTimer() {
if (this.timer) {
window.clearTimeout(this.timer);
this.timer = null;
}
}
getSecondsUntilUpdate(seconds: any) {
const min = 60;
const hr = min * 60;
const day = hr * 24;
if (seconds < min) {
// less than 1 min, update every 2 secs
return 2;
} else if (seconds < hr) {
// less than an hour, update every 30 secs
return 30;
} else if (seconds < day) {
// less then a day, update every 5 mins
return 300;
} else {
// update every hour
return 3600;
}
}
}

但是这段代码抛出了很多异常,特别是当从几秒钟前到1分钟和x分钟前更改时。所以我做了这个改变,这对不经常显示错误有很大的改善这就是我现在已经实现的修改代码

if (Number.isNaN(seconds)) {
return '';
} else if (seconds <= 45) {
return 'a few seconds ago';
} else if (minutes <= 45 && seconds > 45) {
return minutes === 1 ? minutes + ' minute ago' : minutes + ' minutes ago';
} else if (minutes <= 90 && minutes > 45) {
return 'an hour ago';
} else if (hours <= 22 && minutes > 90) {
return hours + ' hours ago';
} else if (hours <= 36 && hours > 22) {
return 'a day ago';
} else if (days <= 25 && hours > 36) {
return days + ' days ago';
} else if (days <= 45 && days > 25) {
return 'a month ago';
} else if (days <= 345 && days > 45) {
return months + ' months ago';
} else if (days <= 545 && days > 345) {
return 'a year ago';
} else {
// (days > 545)
return years + ' years ago';
}

但我仍然有一些错误,而让应用程序运行一段时间

表达式在检查后发生了变化。前一个值:"几秒钟前"。当前值:'1 minute ago'(这个出现的次数最多)

表达式在检查后发生了变化。上一个值:"1分钟前"。当前值:'2 minutes ago'

表达式在检查后发生了变化。上一个值:'3 hours ago'。当前值:'4 hours ago'.

是否有人可以注意到任何可能的改变来改善这种行为?我把"纯粹"说成是假的,因为我读到有些人用它来解决很多问题。但还是一样的。

组件上的实现是

<span>{{data.time | dateAgo }}</span>

并且我已经在declarations部分的@NgModule中导入了组件主模块上的管道

管道不应该包含与其所在视图相关的逻辑。

我的意思是管道不应该有计时器,不应该自己处理所有的值变化:管道只是以一种不同于它接收到的方式显示值。

所以,如果你想做这样的事情,你应该让组件更新视图,使用计时器和更改检测触发器。

不要忘记把你的管道设置为不纯的,因为输入不会改变(或者你可以反过来,让组件更新值,这样你的管道就是纯的)。

下面是一个例子

最新更新