как запланировать 1 таймер в приложении-сервисе не является одноэлементным?

#angular #timer #rxjs #singleton #angular-services

#угловатый #таймер #rxjs #синглтон #angular-services #angular #одноэлементный #angular-сервисы

Вопрос:

Я хотел бы отправлять запрос get каждые X секунд. Я использовал таймер в конструкторе сервиса. Служба внедряется в компонент, который ее использует. Я бы хотел, чтобы служба (как синглтон) планировала запросы get каждые X секунд — как один экземпляр в приложении, независимо от того, сколько браузеров перенаправлено на компонент, в который внедряется служба. В настоящее время кажется, что каждый новый сеанс запускает новый таймер. Обновление : После расследования я выяснил, что основной причиной этого является тот факт, что по какой-то причине служба не является одноэлементной, хотя она объявлена как @Injectible (предоставлено: ‘root’ ). Я даже пытался проверить переменную subscribe : Subscription — чтобы увидеть, есть ли она уже там — и при достижении ее с нового маршрута к компоненту (новый браузер) — она не определена, поэтому это не помогло. Это мой код:

Служба:

 @Injectible(
   providedIn: 'root'
)
export class MyService
{
    subscribe : Subscription; 
    dataSubject = new Subject<any>();
    datasubjectChanged : Observable<any> = this.dataSubject.asObservable();
    constructor(private httpClient : HttpClient)
    {
        if (!this.subscribe)
        {
           this.subscribe = timer(0, 10000)
            .pipe(
                switchMap(() => this.getData()
                .pipe(catchError(error =>
               {
                   return of ("problems in getting data");
               }
            )))).subscribe();
       }
    }
    
    getData(): Observable<any>
    {
        return this.httpClient.get<any>(<rlevantUrl>).
        pipe(response => 
        {
            this.dataSubject.next(response);
        }),
        catchError(err => {
            return throwError(err);
        })
    }
}
  

Это компонент:

 export class Mycomponent(private mySrv : MyService)
{
    ngOnInit()
    {
        let sub = this.mySrv.datasubjectChanged.subscribe(result => dosomething(result)); 
    }
}
  

Комментарии:

1. Что вы имеете в виду под no matter how many browsers are routed to the component where the service is injected into. ?

2. Я имею в виду, что в настоящее время — когда я когда-либо направляюсь к компоненту — он достигает конструктора сервиса, и поэтому — установка нового таймера с новыми повторениями.

3. опять же, что вы имеете в виду new browser ? как вы ожидаете, что это сработает?

4. Я бы ожидал, что в приложении будет 1 экземпляр этой службы, что означает — только 1 таймер поднимается и работает, работая в области приложения. Я попытался выполнить проверку: if (!this.subscribe) — надеясь, что он узнает, что подписка уже создана — но это не так. Мне нужен 1 таймер (возможно, даже выполнить его как-то при начальной загрузке) — все компоненты, которые зависят от этого сервиса, будут подключены к одному и тому же таймеру

Ответ №1:

Служба Angular по умолчанию является одноэлементной по своей природе, и они создаются, когда вы направляетесь к компоненту, в который он был введен и который никогда не уничтожался.

Если только вы не добавляете его в провайдер компонента.

И если вы хотите make get request every X seconds , вы могли бы использовать rxjs interval

 // RxJS v6 
import { interval } from 'rxjs';

//emit value in sequence every 1 second
const source = interval(1000);
//output: 0,1,2,3,4,5....
const subscribe = source.subscribe(val => console.log(val));
  

и в основном сделайте свой http-вызов в нем.