#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-вызов в нем.