1

J'apprends à utiliser angular (4) pour le frontal de mon backend api REST.Consommer périodiquement des données du service http en utilisant Observable in Angular 2/4

J'ai actuellement un composant PostList qui affiche une liste de messages. Im en utilisant un retournant un Observable> dans mon daoService, et en l'insérant dans le onInit dans mon PostListComponent. Tout cela fonctionne très bien et je suis assez heureux avec lui, mais je voudrais utiliser quelque chose comme intervalle pour faire automatiquement cet appel tous les, disons, 5 secondes. J'ai d'abord essayé de suivre un modèle similaire à celui du site angulaire officiel au https://angular.io/docs/ts/latest/tutorial/toh-pt6.html#!#sts=Observables, mais le cas d'utilisation est assez différent et la structure de mon projet est suffisamment importante pour que j'aie de réels problèmes à la suivre de manière utile et ai finalement abandonné . J'ai google autour beaucoup et j'ai du mal à trouver un moyen simple de savoir comment je peux consommer périodiquement des données de mon API en utilisant le modèle observateur/abonné avec un certain intervalle.

Toute suggestion sur la façon dont je peux adapter le code suivant pour faire l'appel à intervalles serait très utile pour moi, et j'imagine, beaucoup d'autres devs nouveaux à angulaire.

import { Injectable } from '@angular/core'; 
import { Http, RequestOptions } from '@angular/http'; 
import {Post} from '../class/post'; 
import 'rxjs/add/operator/toPromise'; 
import {Observable} from 'rxjs/Rx'; 
import 'rxjs/add/operator/map'; 
import 'rxjs/add/operator/catch'; 

@Injectable() 
export class PostDaoService  { 

    private jwt: String; 

    private commentsUrl = 'http://MYDOMAIN/posts'; 

    constructor(private http: Http, private opt: RequestOptions) { 
    // tslint:disable-next-line:max-line-length 
    this.jwt = 'eyJhbGciOiJIUzUxMiJ9.eyJzdWIiOiJQYXNjYNFHUHSFWQiOiIxMjMiLCJyb2xlIjoiYWRtaW4ifQ.4D9TUDQAgIWAooyiMN1lV8Y5wVCrIF4rAeGzFzelSE9diqHMik9WE9x4EsNnEcxQXYATjxAZovpp-m72LpFADA'; 
    } 

    getPosts(): Observable<Array<Post>> { 
    this.opt.headers.set('Authorization', 'Bearer ' + this.jwt); 
    this.opt.headers.set('Content-Type', 'application/json'); 
    return this.http.get(this.commentsUrl) 
     .map((response) => response.json()) 
     .map((data: any) => { 
     return data._embedded.posts as Post[]; 
     }); 
    } 
} 

import { ContextMenuService } from '../../../baseui-module/context-menu/context-menu.service'; 

import { Post } from '../../class/post'; 
import { PostDaoService } from '../../service/post-dao.service'; 
import {Component, Input, OnInit} from '@angular/core'; 

@Component({ 
    selector: 'app-post-list', 
    templateUrl: './post-list.component.html', 
    styleUrls: ['./post-list.component.css'] 
}) 
export class PostListComponent implements OnInit { 

    posts: Post[]; 

    constructor(public service: ContextMenuService, public dao: PostDaoService) { } 

    ngOnInit() { 
    this.service.postItems(); 
    this.dao.getPosts().subscribe((data: Array<Post>) => { 
     this.posts = data; 
    }); 
    } 

    public getItems(): Post[] { 
    return this.posts; 
    } 
} 

Répondre

0

L'astuce consiste à utiliser un mergeMap/flatMap (selon la version rxjs):

getPosts(trigger: Observable<any>): Observable<Array<Post>> { 
    this.opt.headers.set('Authorization', 'Bearer ' + this.jwt); 
    this.opt.headers.set('Content-Type', 'application/json'); 
    return trigger.flatMap(() => 
    this.http.get(this.commentsUrl) 
     .map((response) => response.json()) 
     .map((data: any) => { 
     return data._embedded.posts as Post[]; 
     }); 
} 

Et puis dans votre composant:

this.dao.getPosts(Observable.timerInterval(0, 5000) 
    .subscribe(data => ....); 

Évidemment, vous pouvez l'utiliser avec autres déclencheurs:

this.dao.getPosts(Observable.fromEvent(refreshButton, 'click')) 

Pour rafraîchir lorsque le bouton de rafraîchissement est cliqué

BTW, vous voudrez peut-être éviter la souscription et au lieu de définir:

this.posts$ = this.dao.getPosts(...); 

et dans votre modèle:

<any *ngFor="let post of posts$">post display here</any> 

Ce sera plus efficace et réduit le risque d'abonnés pendants et de fuites de mémoire.

+0

Malheureusement timerInterval (n, m) n'est pas disponible dans Observable, donc j'ai changé à intervalle (5000) qui a corrigé l'erreur de compilation, mais j'ai maintenant l'erreur suivante: core.es5.js: 1084 ERROR Error: Uncaught (en promesse): TypeError: __WEBPACK_IMPORTED_MODULE_3_rxjs_Observable __. Observable.interval n'est pas une fonction TypeError: __WEBPACK_IMPORTED_MODULE_3_rxjs_Observable __. Observable.interval n'est pas une fonction – gezinspace

+0

Avez-vous ajouté une importation? Je pense que c'est import 'rxjs/observable/add/interval' – Meir

+0

Je viens de l'importer explicitement et maintenant il est dit que flatMap (ou mergeMap) n'est pas une fonction. essayé d'importer ceux-ci explicitement mais ne va nulle part. Edit: aussi, si j'échange temporairement la variable trigger pour l'objet Observable avec. afin que je puisse inspecter l'API, aucune de ces fonctions n'est disponible – gezinspace