有没有什么方法可以让我确定哪个Angular 信号导致了效果的执行?我在一个组件中有两个信号和一个效果.对于一个信号,我想在服务中启动一个计时器功能.另一个信号基于服务定时器功能中不断变化的条件,并且可以频繁地改变.

我有一个变通的解决方案,但知道是哪个信号引起了这种影响会很有用.解决方法是在计时器启动时在服务中设置isTimerRunning布尔值.

以下是我的代码:

import { Injectable, Signal, WritableSignal, signal } from '@angular/core';
import { Observable, Subscription, merge, fromEvent, timer, BehaviorSubject } from 'rxjs';
import { environment } from '../../environments/environment';
import { LocalStorageService } from './storage.service';

export interface IIdleTimeoutModel {
  expired: boolean;
  expiring: boolean;
}

@Injectable({
  providedIn: 'root',
})

export class IdleTimeoutService {
  constructor(private localStorageService: LocalStorageService) { }

  idleTimeout: IIdleTimeoutModel = { expired: false, expiring: false }
  private idleSignal: WritableSignal<IIdleTimeoutModel> = signal(this.idleTimeout);
  readonly idleSignalModel: Signal<IIdleTimeoutModel> = this.idleSignal.asReadonly();
  
  private idleEventTriggers: Observable<any> = new Observable();
  private timer: Subscription = new Subscription();
  private timeOutMilliSeconds: number = 1000;
  private timeOutWarningMilliSeconds: number = 1000;
  private isTimerRunning: boolean = false;

  public startWatching(): void {
    if (!this.isTimerRunning) {
      this.timeOutMilliSeconds = environment.idleTimeInMilliseconds;
      this.timeOutWarningMilliSeconds = environment.idleTimeWarningInMilliseconds;
  
      this.idleEventTriggers = merge(
        fromEvent(document, 'click'),
        fromEvent(document, 'mousedown'),
        fromEvent(document, 'keypress')
      );
  
      this.idleEventTriggers.subscribe((res) => {
        this.resetTimer();
      });
  
      this.startTimer();
     }

  }

  private startTimer() {
    this.isTimerRunning = true; // <-- this is what I am currently doing to prevent the signal from staring the timer multiple times
    let timeoutModel: IIdleTimeoutModel = {
      expired: false,
      expiring: false,
    };
    let initDatetime = new Date();
    let timeoutSeconds = this.timeOutWarningMilliSeconds / 1000 + initDatetime.getSeconds();
    let warningSeconds = this.timeOutMilliSeconds / 1000 + initDatetime.getSeconds();
    let expiringDatetime = new Date().setSeconds(timeoutSeconds);
    let expiredDatetime = new Date().setSeconds(warningSeconds);

    this.localStorageService.set('expiringDatetime', expiringDatetime.toString());
    this.localStorageService.set('expiredDatetime', expiredDatetime.toString());

    // timer
    this.timer = timer(1000, 5000).subscribe((response) => {

      let nowDatetime = new Date();

      // expiringDatetime
      let checkExpiringDatetimeValue = this.localStorageService.get('expiringDatetime');
      if (checkExpiringDatetimeValue) {
        if (nowDatetime.getTime() >= parseInt(checkExpiringDatetimeValue)) {
          this.idleSignal.set({ expiring: true, expired: false })
        } else {
          this.idleSignal.set({ expiring: false, expired: false })
        }
      } else {
        this.resetTimer();
      }

      // expiredDatetime
      let checkExpiredDatetimeValue = this.localStorageService.get('expiredDatetime');
      if (checkExpiredDatetimeValue) {
        if (nowDatetime.getTime() >= parseInt(checkExpiredDatetimeValue)) {
          if (timeoutModel.expired === false) {
            timeoutModel.expired = true;
            this.idleSignal.set({ expiring: false, expired: true })
          }
        } else {
          if (timeoutModel.expired === true) {
            timeoutModel.expired = false;
            this.idleSignal.set({ expiring: false, expired: true })
          }
        }
      } else {
        this.resetTimer();
      }
    });
  }

  public resetTimer() {
    this.timer.unsubscribe();
    this.idleSignal.set({ expiring: false, expired: false })
    this.startTimer();
  }

  public stopTimer() {
    this.isTimerRunning = false;
    this.timer.unsubscribe();
  }
}

组件(APP组件):

// Variables declare in the component:

  isLoggedIn = this.appService.isLoggedInSignal; // this is a signal in our app service that is set when a user log in
  private idleTimeoutSignalModel = this.idleTimeoutService.idleSignalModel; // this is a signal from the IdleTimeoutService service above. this will change based on the timer function


In the constructor:
    effect(() => {
      if (this.isLoggedIn() && environment.idleTimeout) {
        const idleModel = this.idleTimeoutSignalModel();
        
        this.idleTimeoutService.startWatching(); // <-- this is the function I want to only run once based on isLoggedIn signal chnaging
        
        if (idleModel.expiring) {
          this.dialogService.openTimeOutDialog('Extend Session?', 'Due to inactivity, your login session will expire shortly. Do you want to continue?');
        } else {
          this.dialogService.closeDialogById('timeout-dialog');
        }

        if (idleModel.expired) {
          try {
            this.broadcastService.publish({
              type: 'mnsso-logout',
              payload: 'true',
            });
          } catch {
            console.log('broadcast error');
          }
          this._authService.logout();
        }
      }
    });

推荐答案

当他们的react node 被标记为脏时,效果就会被激发.

在 compose 本文时,还没有跟踪哪个信号会使另一个信号变脏.

因此,没有办法确定哪个信号触发了一种效应.

Angular相关问答推荐

NG构建后多余的国旗

尽管有模拟间谍实现,规范文件仍调用真正的服务

图像未显示在视图屏幕上-Angular 投影

ANGLE DI useFactory将参数传递给工厂函数

ANGLE v16独立组件不能与拦截器一起工作?

一个接一个的Angular http请求,但只关心第一个

是否可以在Angular(12+)中迭代指定的范围而不是整个数组

如何根据响应变化更改 Angular Carousel 的cellsToShow

执行ng generate environments时出错时需要合集和原理图

为什么 AngularFire .set() 永远等待响应并且不继续?

如何以Angular 2 获取当前路由自定义数据?

Angular 2如何使用路由和location.go()检测后退按钮按下?

无法读取 angular2 中未定义(…)的属性 push

angular4应用程序中输入的最小值和最大值

错误:您要查找的资源已被删除、名称已更改或暂时不可用

如何在angular 5的组件中格式化日期

angular 2模板使用console.log

Angular:ViewChild 上未定义 nativeElement

样式 html,来自 Web 组件的正文

如何对 *ngFor 应用数量限制?