如何在Angular中动态计算Call类对象的通话时长?
解决方案
问题分析
你原来的代码存在几个核心问题:
setInterval内部使用普通函数导致this指向错误,无法正确更新实例的duration属性- 时长计算逻辑错误:
creationDate是时间戳,正确的时长应该是当前时间戳 - creationDate,而非直接加1 - 在类属性初始化阶段调用
calculateDuration,会给每个Call实例单独创建定时器,既浪费资源又难以统一管理
修正步骤
1. 还原Call类为纯数据类
先把Call类改回最初的结构,不要在类中嵌入定时器逻辑:
export class Call { ucid: string; state: string; originator: Originator; destination: Destination; language: string; server: string; creationDate: number; // 确保是毫秒级时间戳 duration?: string; // 留空,由组件动态计算赋值 }
2. 在组件中统一管理定时器与时长计算
在组件层面统一处理所有通话的实时时长更新,便于控制定时器启停,避免内存泄漏:
import { Component, OnInit, OnDestroy } from '@angular/core'; import { CallService } from './call.service'; import { Call } from './call.model'; @Component({ selector: 'app-call-list', template: ` <ul> <li *ngFor="let call of calls"> 通话ID: {{call.ucid}} - 实时时长: {{call.duration || '00:00:00'}} </li> </ul> ` }) export class CallListComponent implements OnInit, OnDestroy { calls: Call[] = []; private durationTimer?: number; constructor(private callService: CallService) {} ngOnInit(): void { this.callService.getCalls().subscribe(calls => { this.calls = calls; // 数据加载完成后启动定时器,每秒更新一次时长 this.startDurationUpdate(); }); } ngOnDestroy(): void { // 组件销毁时清除定时器,防止内存泄漏 if (this.durationTimer) { clearInterval(this.durationTimer); } } private startDurationUpdate(): void { this.durationTimer = window.setInterval(() => { this.calls.forEach(call => { // 计算总秒数:当前时间戳 - 通话创建时间戳,转成秒 const totalSeconds = Math.floor((Date.now() - call.creationDate) / 1000); // 格式化为hh:mm:ss格式 call.duration = this.formatDuration(totalSeconds); }); }, 1000); } private formatDuration(totalSeconds: number): string { const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = totalSeconds % 60; // 补零处理,确保每个时间部分都是两位数字 return [ hours.toString().padStart(2, '0'), minutes.toString().padStart(2, '0'), seconds.toString().padStart(2, '0') ].join(':'); } }
3. 关键细节说明
- 定时器生命周期:在
ngOnInit中数据加载完成后启动定时器,ngOnDestroy中清除,避免组件销毁后定时器仍在运行 - 时长计算逻辑:用
Date.now()获取当前毫秒级时间戳,与通话的creationDate做差后转成秒数 - 格式化处理:通过数学运算拆分小时、分钟、秒,用
padStart(2, '0')确保不足两位时自动补零
可选优化:使用Angular管道格式化
如果不想修改Call实例的duration属性,可以自定义管道在模板中实时计算:
定义管道
import { Pipe, PipeTransform } from '@angular/core'; @Pipe({ name: 'callDuration' }) export class CallDurationPipe implements PipeTransform { transform(creationDate: number): string { const totalSeconds = Math.floor((Date.now() - creationDate) / 1000); const hours = Math.floor(totalSeconds / 3600); const minutes = Math.floor((totalSeconds % 3600) / 60); const seconds = totalSeconds % 60; return [ hours.toString().padStart(2, '0'), minutes.toString().padStart(2, '0'), seconds.toString().padStart(2, '0') ].join(':'); } }
模板中使用
<ul> <li *ngFor="let call of calls"> 通话ID: {{call.ucid}} - 实时时长: {{call.creationDate | callDuration}} </li> </ul>
这种方式无需修改Call实例,但如果通话数量较多,频繁的变更检测可能影响性能,此时定时器批量更新的方式更高效。
内容的提问来源于stack exchange,提问作者Flamur Dervishi
相关产品推荐
相关产品推荐

