web-dev-qa-db-fra.com

Comment obtenir un observable pour renvoyer des données immédiatement et toutes les 5 secondes par la suite

Je veux créer un observable qui renvoie les données d'une webapi. Je voudrais qu'il renvoie immédiatement les données et interroge l'API toutes les 10 secondes. Le code ci-dessous montre que j'utilise la méthode "intervalle". Mais cela retarde le premier ensemble de données de 10 secondes. Comment puis-je obtenir ce premier flux de données sans retard initial?

export class EventService {
    public events$: Observable<Event[]>;
    private _eventsObserver: Observer<Event[]>;
    private pollInterval: number = 5000;

    private _dataStore: {
        events: Event[];
    };

    constructor(private http: Http) {
        this._dataStore = { events: [] };

        this.events$ = new Observable(observer => this._eventsObserver = observer)
            .startWith(this._dataStore.events)
            .share();
    }

    pollEvents() {
        return Observable.interval(10000)
            .switchMap(() => {
                return this.http.get('app/resources/data/scheduleevents.json')
                    .map((responseData) => {
                        return responseData.json();
                    });
            })
            .map((events: Array<any>) => {
                let result: Array<Event> = [];
                if (events["data"]) {
                    events["data"].forEach((event) => {
                        result.Push(event);
                    });
                }
                return result;
            });
    }
}
37
FeeFiFoFum

Je l'ai:

        .interval(5000)
        .startWith(0);
75
FeeFiFoFum

Utilisez la minuterie. Je pense que le timer est ce dont vous avez besoin (voir l'onglet RxJS): http://reactivex.io/documentation/operators/timer.html#collapseRxJS

Pourrait être utilisé comme:

Observable.timer(0, 5000).flatMap(() => apiCall())

0 - délai avant l'émission de la première valeur, 5000 - émet une valeur toutes les 5 secondes

enter image description here

20
Alendorff
    let timer = TimerObservable.create(0, 5000);
    this.sub = timer.subscribe(t => {
        this.yourMethod()
    });

Pour résilier votre abonnement, exécutez this.sub.unsubscribe()

3
Yossi Neiman
Observable.interval(5L, TimeUnit.SECONDS)
        .startWith(0)
        .observeOn(AndroidSchedulers.mainThread())
        .map { foobar() }

fonctionne bien pour moi. Merci

0
SebLu

Pour angualr2 ci-dessous est le code que j'ai écrit dans mon application et il fonctionne comme prévu -

En service --

import { Observable } from 'rxjs/Observable';
import 'rxjs/Rx';

getList(): Observable<IVM> {
    return Observable.interval(5000).startWith(0)
          .switchMap(() => 
             this._http.get(this._vmURL )
                 .map((response: Response) => <IVM>response.json().data)
                 .do(data => console.log('All: ' + JSON.stringify(data)))
                .catch(this.handleError)
             );
}

Dans le composant -

private getInstanceDetails(): void {
    this._vmDataService.getList()
        .subscribe(vmList => {
           //Do whatever you want with the vmList here :) 
        },
        error => this.errorMessage = <any>error);
}

Merci, veuillez me faire part de vos pensées.

0

J'utilise personnellement interval avec startWith (besoin RxJs 6 +), voici un exemple complet:

   history: any;
   historySubscription: Subscription;

   constructor(private jobService: JobService) { }

   ngOnInit() {

      this.historySubscription = interval(10000).pipe(
         startWith(0),
         flatMap(() => this.jobService.getHistory())
      ).subscribe(data => {
         this.history = data;
      });

   }

   ngOnDestroy() {
      this.historySubscription.unsubscribe();
   }

Cela récupère l'historique à l'init puis toutes les 10 secondes.

Une autre alternative consiste à utiliser timer comme expliqué par @Alendorff.

0
Curse