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

首次加载Service Worker注册前SwUpdate无法正常工作问题

问题分析与解决方案

核心问题

首次加载时你的NewAppVersionTrackerService初始化过早——此时Service Worker还没完成注册(因为用了registerWhenStable:30000策略),this.swUpdate.isEnabled返回false,直接跳过了所有监听逻辑;而SW注册完成后,你的服务没有重新触发这些逻辑,导致SwUpdate与SW完全脱节。刷新页面时SW已提前注册,isEnabled为true,所以逻辑正常运行。

修复方案

方案1:监听SwUpdate.isEnabled变化,动态启动监听逻辑

修改服务代码,在isEnabled状态变为true时自动初始化更新监听,避免因SW未就绪导致逻辑跳过:

// new-app-version-tracker.service.ts
@Injectable({ providedIn: 'root' })
export class NewAppVersionTrackerService {
  private checkIntervalSeconds = 300;
  private updateSubscription?: Subscription;
  private intervalSubscription?: Subscription;

  constructor(
    private dialogService: DialogService,
    private swUpdate: SwUpdate,
    private zone: NgZone,
  ) {}

  public init() {
    // 监听isEnabled状态变化,动态启停监听逻辑
    this.swUpdate.isEnabled.subscribe((enabled) => {
      enabled ? this.startUpdateWatch() : this.stopUpdateWatch();
    });

    // 初始检查一次状态
    if (this.swUpdate.isEnabled.value) {
      this.startUpdateWatch();
    }
  }

  private startUpdateWatch(): void {
    if (this.updateSubscription) return;

    // 订阅版本更新事件
    this.updateSubscription = this.swUpdate.versionUpdates.subscribe((versionEvent) => {
      switch (versionEvent.type) {
        case 'VERSION_DETECTED':
          console.info(`发现新版本,开始下载: ${versionEvent.version.hash}`);
          break;
        case 'VERSION_READY':
          console.info(`新版本已就绪: ${versionEvent.latestVersion.hash}`);
          this.dialogService.open(DynamicNewApplicationVersionReadyDialogComponent);
          break;
        case 'VERSION_INSTALLATION_FAILED':
          console.warn(`新版本下载失败 (hash: ${versionEvent.version.hash}): ${versionEvent.error}`);
          break;
      }
    });

    // 启动定时更新检查
    this.zone.runOutsideAngular(() => {
      this.intervalSubscription = interval(this.checkIntervalSeconds * 1000).subscribe(() => {
        console.log('检查SW更新');
        this.swUpdate.checkForUpdate()
          .then((versionFound) => console.log('更新检查结果:', versionFound))
          .catch(err => console.error('更新检查失败:', err)); // 新增错误捕获,避免Promise挂起
      });
    });
  }

  private stopUpdateWatch(): void {
    this.updateSubscription?.unsubscribe();
    this.intervalSubscription?.unsubscribe();
    this.updateSubscription = undefined;
    this.intervalSubscription = undefined;
  }
}

方案2:在APP初始化阶段等待SW注册完成

通过APP_INITIALIZER让应用等待SW注册完成后再初始化服务,确保服务启动时SW已就绪:

// app.config.ts
export const appConfig: ApplicationConfig = {
  providers: [
    provideServiceWorker('ngsw-worker.js', {
      enabled: !isDevMode(),
      registrationStrategy: 'registerWhenStable:30000',
    }),
    {
      provide: APP_INITIALIZER,
      useFactory: (swUpdate: SwUpdate) => () => 
        new Promise(resolve => {
          // 轮询检查SW是否就绪
          const checkTimer = setInterval(() => {
            if (swUpdate.isEnabled.value) {
              clearInterval(checkTimer);
              resolve(true);
            }
          }, 1000);
          // 超时兜底,避免阻塞应用启动
          setTimeout(() => {
            clearInterval(checkTimer);
            resolve(true);
          }, 35000);
        }),
      deps: [SwUpdate],
      multi: true,
    },
    NewAppVersionTrackerService,
  ],
};

方案3:直接监听浏览器SW注册事件

通过浏览器原生API监听SW注册状态,确保SW就绪后再启动更新逻辑:

// new-app-version-tracker.service.ts
private waitForSwRegistration(): Promise<void> {
  return new Promise(resolve => {
    // 若SW已激活,直接resolve
    if (navigator.serviceWorker.controller) {
      resolve();
    } else {
      // 监听SW控制器变更事件(注册完成触发)
      navigator.serviceWorker.addEventListener('controllerchange', () => {
        resolve();
      });
      // 超时兜底
      setTimeout(resolve, 35000);
    }
  });
}

public async init() {
  await this.waitForSwRegistration();
  if (this.swUpdate.isEnabled) {
    this.watchForUpdates();
  }
}

额外注意事项

  • 生产环境测试时,确保每次部署都更新资源哈希(Angular CLI会自动处理,若手动部署需同步ngsw-config.json),否则SW无法检测到新版本。
  • 必须为checkForUpdate()添加错误捕获,避免Promise因异常挂起无响应。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 01:52:13