Как получить наблюдаемое значение от любого компонента в Angular? - PullRequest
0 голосов
/ 13 марта 2020

У меня есть приложение, защищенное страницей входа, и я пытаюсь реализовать простой таймер сеанса, скажем, если пользователь не обновил sh или не сделал что-либо в приложении (то есть, не go через OnInit ( )) приложение должно выгнать пользователя

В настоящее время у меня есть app component следующая функция

subscribeTimer: any;
minutes = 0;
seconds = 0;
timeLeft = 12;


ObservableTimer() {
    const source = timer(1000, 1000);
    const abc = source.subscribe(val => {
      if (this.subscribeTimer === 1) {
        abc.unsubscribe();
        this.alertfy.alert('Session Timed Out', 'Your session has been expired!', () => { this.logOut(); }, false);
      }
      this.subscribeTimer = this.timeLeft - val;
      this.minutes = Math.floor(this.subscribeTimer / 60);
      this.seconds = Math.floor(this.subscribeTimer - this.minutes * 60);
    });
  }

Я импортирую timer из rxjs

Затем я добавляю минуты / секунды в свой компонент. html вот так

<div *ngIf="isLoggedIn" style="text-align: right;"><p>Time Left: {{minutes}}:{{seconds}}</p></div>

В настоящее время я вызываю функцию ObservableTimer() в моем OnInit() этого app component из-за того, что я не подписался на это можно наблюдать, пока я не обновлю sh страницу, когда я уже вошел в систему, как показано ниже:

ngOnInit(): void {

    const token = localStorage.getItem('token');
    if (token) {
        this.oberserableTimer();
    }
}

Я хочу иметь возможность запустить это наблюдаемое из другого сервиса, называемого auth.service.ts, который обрабатывает этот сервис логин и my app component могут получить доступ к любой функции в нем, потому что она внедрена в конструктор app component. Другими словами, когда пользователь входит в систему, запустите наблюдаемое в моей службе аутентификации и позвольте компоненту приложения подписаться на это наблюдаемое и прочитать его значение и соответственно обновить html.

Плюс, я хочу иметь возможность сбросить это время с любого компонента, скажем, пользователь щелкнул по чему-то или перешел на другую страницу. Я хочу иметь возможность сбросить таймер.

Ответы [ 2 ]

1 голос
/ 13 марта 2020

Вы на правильном пути. Поместите функцию таймера / переменные в сервис аутентификации. Затем добавьте свой сервис в любой конструктор, который вы хотите. Вы сможете вызвать функцию или использовать переменные, выполнив что-то вроде this.service.function(). Вы можете прочитать здесь: https://angular.io/guide/dependency-injection#injecting -услуги

Редактировать -

Ах, после понимания вашего варианта использования я бы предложил следующее. Вы действительно не хотите, чтобы ваши службы слишком много думали, если это имеет смысл. Диалоговое окно с предупреждением в приведенном ниже коде откроет пользователю всплывающее окно, сообщающее ему, что его сеанс истекает.

В app.component.ts:

public constructor() {
  //Begins keeping track of the timers
  this.setWarningTimeout();
  this.setLogoutTimeout();
  //If the inactivity reaches the threshold, run these functions
  this.userInactiveWarning.subscribe(() => this.openWarningDialog());
  this.userInactiveLogout.subscribe(() => this.logoutUser());
}

//Sets the warning timer to 25 minutes
private setWarningTimeout() {
  this.userActivityWarning = setTimeout(() => 
  this.userInactiveWarning.next(undefined), 1500000);
}

//Sets the logout timer to 30 minutes
private setLogoutTimeout() {
  this.userActivityLogout = setTimeout(() => 
  this.userInactiveLogout.next(undefined), 1800000);
}

//Listens for mouse movement
//If user moves mouse, then it will reset the timer
@HostListener('window:mousemove') refreshUserState() {
  clearTimeout(this.userActivityWarning);
  clearTimeout(this.userActivityLogout);
  this.setWarningTimeout();
  this.setLogoutTimeout();
}
0 голосов
/ 13 марта 2020

Может быть, у вас может быть служба обратного отсчета, чтобы делать то, что вы хотите. Если вы создаете службу обратного отсчета в виде одиночного, вы можете получить к нему доступ из любого компонента, в вашем коде ваша служба аутентификации отправит действие службе обратного отсчета, чтобы инициировать обратный отсчет при входе пользователя в систему.

Ваш компонент получает статус или свойства из службы обратного отсчета, чтобы получить оставшееся время.

Таким образом, другие компоненты могут внедрить вашу службу обратного отсчета и сбросить обратный отсчет.

Пример, чтобы уточнить.

Чтобы помочь вам описательным способом, я написал фиктивный метод для создания обратного отсчета. Вы можете улучшить его позже.

Примечание. В этом примере я игнорирую большой объем кода. Я пишу только важный код для пояснения решения.

import { timer } from 'rxjs';
import { takeWhile, tap } from 'rxjs/operators';

// This service needs to be a singleton
export class CountdownService {
  private timeleft: number; // in secs

  initCountdown() {
     const timestamp = 999999; // set your timestamp
     // create my timer
     timer(0, 1000)
      .pipe(
        tap(() => {
          // timeleft in secs
          this.timeleft = Math.round(
            (timestamp - Date.now()) / 1000
          );
        }),
        takeWhile(() => this.timeleft > 0) // unsubscribe when timeleft is 0
      )
      .subscribe();
  }

  getTimeLeft(): number {
    return this.timeleft;
  }

  reset() {}
}
import { Observable, BehaviorSubject } from 'rxjs';

export class AuthService {
  // this behavior subject store the auth state
  private authSubject$ = new BehaviorSubject<boolean>(false);

  constructor(private countdownService: CountdownService) {} // inject my countdown service

  signIn(): void {
    // ... your sign-in logic
    if (loggedIn) {
      // authSubject$ is now true, in order to spread the state
      // now other components can subscribe to the observable
      // to know wha is the auth state
      this.authSubject$.next(true);
    }
  }

  signOut(): void {
    // set false on signing out
    this.authSubject$.next(false);
  }

  isAuth$(): Observable<boolean> {
    // get the auth state as an observable
    return this.authSubject$.asObservable();
  }
}
import { filter } from 'rxjs/operators';

export class ComponentA {
  constructor(private countdownService: CountdownService, private authService: AuthService) {}

  getAuthState() {
    this.authService.isAuth$()
    .pipe(filter((isAuth) => isAuth))
    .subscribe(() => {
      // user is logged in
      this.timeLeft = this.countdownService.getTimeleft();
    });
  }
}
export class ComponentB {
  constructor(private countdownService: CountdownService) {}

  ngOnInit() {
    // on entering page reset countdown
    this.countdownService.reset();
  }
}
...