You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.25 19:27:23