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

AngularJS TypeScript项目中如何监听普通TS文件的方法/事件?

如何在AngularJS TypeScript项目中订阅/监听普通TypeScript文件中的事件/方法?

针对你遇到的这个问题,咱们可以用几种不依赖AngularJS依赖注入体系的方案,轻松让ribbonController感知到progressBar.ts里的加载完成状态,完全适配你那个纯TS文件的场景:

方案一:给progressBar.ts添加回调订阅机制

我们可以在纯TS文件里维护一个回调函数队列,当加载进度达到100%时,自动触发所有已订阅的回调。这种方式简单直接,不需要依赖任何框架API:

修改progressBar.ts:

// progressBar.ts
let loadComplete = false;
// 存储所有订阅加载完成事件的回调函数
const completionCallbacks: (() => void)[] = [];

export function updateGlobalProgressBar(progress: number) {
  // 保留你原来的进度更新逻辑
  // ...

  // 当进度达到100%时标记完成,并触发所有回调
  if (progress >= 100 && !loadComplete) {
    loadComplete = true;
    completionCallbacks.forEach(callback => callback());
  }
}

// 提供订阅方法,外部可以注册回调
export function onLoadingComplete(callback: () => void) {
  // 如果加载已经完成,直接触发回调(避免错过事件)
  if (loadComplete) {
    callback();
  } else {
    completionCallbacks.push(callback);
  }
}

export function loadingComplete(): boolean {
  return loadComplete;
}

在ribbonController中使用:

// ribbonController.ts
import { onLoadingComplete } from './progressBar';

class RibbonController {
  constructor(private _scope: any) {
    // 订阅加载完成事件
    onLoadingComplete(() => {
      // 因为回调是在AngularJS的 digest 循环外触发的,需要用$apply通知视图更新
      this._scope.$apply(() => {
        this._scope.loaderHasLoaded = true;
      });
    });
  }
}

方案二:使用浏览器原生的自定义事件

利用浏览器的EventTarget API,让progressBar.ts触发自定义事件,然后在控制器中监听这个事件,这种方式更符合浏览器的事件驱动模型:

修改progressBar.ts:

// progressBar.ts
let loadComplete = false;
// 创建一个事件目标对象,用来触发和监听自定义事件
export const progressBarEvents = new EventTarget();

export function updateGlobalProgressBar(progress: number) {
  // 保留你原来的进度更新逻辑
  // ...

  if (progress >= 100 && !loadComplete) {
    loadComplete = true;
    // 触发名为"loadingComplete"的自定义事件
    progressBarEvents.dispatchEvent(new CustomEvent('loadingComplete'));
  }
}

export function loadingComplete(): boolean {
  return loadComplete;
}

在ribbonController中使用:

// ribbonController.ts
import { progressBarEvents } from './progressBar';

class RibbonController {
  constructor(private _scope: any) {
    const handleLoadingComplete = () => {
      this._scope.$apply(() => {
        this._scope.loaderHasLoaded = true;
      });
      // 如果只需要监听一次加载完成,可以移除事件监听
      progressBarEvents.removeEventListener('loadingComplete', handleLoadingComplete);
    };

    // 注册事件监听
    progressBarEvents.addEventListener('loadingComplete', handleLoadingComplete);

    // 控制器销毁时移除监听,避免内存泄漏
    this._scope.$on('$destroy', () => {
      progressBarEvents.removeEventListener('loadingComplete', handleLoadingComplete);
    });
  }
}

为什么你之前的循环方案不行?

  • do-while循环:会直接阻塞JavaScript线程,导致页面完全卡死,浏览器无法处理任何用户交互或更新视图,绝对不能用这种方式。
  • if语句:只会执行一次判断,如果当时加载还没完成,就再也不会重新检查状态了,自然捕捉不到后续的完成事件。

额外提示

不管用哪种方案,都要记得在控制器销毁时清理订阅(比如移除事件监听),避免内存泄漏。另外,因为纯TS文件的逻辑不在AngularJS的digest循环内,所以更新scope变量时需要用$apply来通知Angular更新视图。

内容的提问来源于stack exchange,提问作者onmyway

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 09:21:28