Angular2 + http à un intervalle

Je suis assez nouveau pour angular et rxjs. J'essaie de créer une application angular2 qui obtient des données à partir d'un fichier texte staticly servi(localement sur le serveur), que je voudrais récupérer et mapper à Datamodel en utilisant le fournisseur http D'Angular2 et la carte de rxjs à une heure fixe interval(5000). Pour refléter les modifications apportées au fichier txt servi.

Avec rxjs 4.x je sais que vous pouvez utiliser Observable.interval(5000) pour faire le travail, mais il ne semble pas exister dans rxjs 5. Ma solution de contournement actualise actuellement toute l'application en utilisant <meta http-equiv="refresh" content="5" > Qui recharge toute la page, et recharge ainsi les données.

Donc, ce que je voudrais vraiment, c'est un moyen de le faire en travaillant avec des observables, peut-être pour vérifier si des changements sont survenus. ou tout simplement pour recharger les données à nouveau.

Toute aide ou autre / meilleure façon sera très appréciée.

Ce que j'ai jusqu'à présent:

@Injectable()
export class DataService {

    constructor(private http:Http){}

    getData(url) {
        return this.http.get(url)
            .map(res => {
                return res.text();
            })
            .map(res => {
                return res.split("n");
            })
            .map(res => {
                var dataModels: DataModel[] = [];
                res.forEach(str => {
                    var s = str.split(",");
                    if(s[0] !== "") {
                        dataModels.push(new DataModel(s[0], parseInt(s[1]), parseInt(s[2])));
                    }
                });
                return dataModels;
            })
    }
}

@Component({
selector: 'my-app',
template: `Some html to display the data`,
providers: [DataService],
export class AppComponent {

data:DataModel[];

constructor(dataService:DataService) {}

ngOnInit() {
    this.dataService.getData('url').subscribe(
        res => {
            this.data= res;

        },
        err => console.log(err),
        () => console.log("Data received")
        );
    }
}

Dépendances: paquet.json

"dependencies": {
  "angular2": "^2.0.0-beta.3",
  "bootstrap": "^4.0.0-alpha.2",
  "es6-promise": "^3.0.2",
  "es6-shim": "^0.33.13",
  "jquery": "^2.2.0",
  "reflect-metadata": "^0.1.2",
  "rxjs": "^5.0.0-beta.0",
  "systemjs": "^0.19.20",
  "zone.js": "^0.5.11"
},
"devDependencies": {
  "typescript": "^1.7.5"
}

Index.importation html:

<script src="node_modules/es6-shim/es6-shim.min.js"></script>
<script src="node_modules/systemjs/dist/system-polyfills.js"></script>

<script src="node_modules/angular2/bundles/angular2-polyfills.js"></script>
<script src="node_modules/systemjs/dist/system.src.js"></script>
<script src="node_modules/rxjs/bundles/Rx.js"></script>
<script src="node_modules/angular2/bundles/angular2.dev.js"></script>
<script src="node_modules/angular2/bundles/router.dev.js"></script>
<script src="node_modules/angular2/bundles/http.dev.js"></script>
53
demandé sur mxr7350 2016-02-10 16:28:46

4 réponses

Comme @Adam et @ Ploppy l'ont mentionné, L'Observable.interval () est maintenant obsolète pas le moyen préféré de créer un tel observable. La façon préférée de le faire est via IntervalObservable ou TimerObservable. [actuellement dans Typscript 2.5.2, rxjs 5.4.3, Angulaire 4.0.0]

Je voulais ajouter un peu d'utilisation à cette réponse pour démontrer ce que j'ai trouvé la meilleure façon de le faire dans le framework Angular 2.

D'abord votre service (créé en cli angulaire via le service ' ng g Commande" MyExample"). En supposant que le service est RESTful (http get request renvoie un json):

Mon-exemple.service.ts

import { Injectable } from '@angular/core';
import { Http, Response} from "@angular/http";
import { MyDataModel } from "./my-data-model";
import { Observable } from "rxjs";
import 'rxjs/Rx';

@Injectable()
export class MyExampleService {
  private url = 'http://localhost:3000'; // full uri of the service to consume here

  constructor(private http: Http) { }

  get(): Observable<MyDataModel>{
    return this.http
      .get(this.url)
      .map((res: Response) => res.json());
  }
}

* * * voir les mises à jour en bas du service pour Angular 5 * * *

Maintenant votre code de composant ("ng g composant MyExample'):

Mon-exemple.composant.ts:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { MyDataModel } from "../my-data-model";
import { MyExampleService } from "../my-example.service";
import { Observable } from "rxjs";
import { IntervalObservable } from "rxjs/observable/IntervalObservable";
import 'rxjs/add/operator/takeWhile';

@Component({
  selector: 'app-my-example',
  templateUrl: './my-example.component.html',
  styleUrls: ['./my-example.component.css']
})
export class MyExampleComponent implements OnInit, OnDestroy {
  private data: MyDataModel;
  private display: boolean; // whether to display info in the component
                            // use *ngIf="display" in your html to take
                            // advantage of this

  private alive: boolean; // used to unsubscribe from the IntervalObservable
                          // when OnDestroy is called.

  constructor(private myExampleService: MyExampleService) {
    this.display = false;
    this.alive = true;
  }

  ngOnInit() {
    // get our data immediately when the component inits
    this.myExampleService.get()
      .first() // only gets fired once
      .subscribe((data) => {
        this.data = data;
        this.display = true;
      });

    // get our data every subsequent 10 seconds
    IntervalObservable.create(10000)
      .takeWhile(() => this.alive) // only fires when component is alive
      .subscribe(() => {
        this.myExampleService.get()
          .subscribe(data => {
            this.data = data;
          });
      });
  }

  ngOnDestroy(){
    this.alive = false; // switches your IntervalObservable off
  }
}

= = = modifier = = =

Mise à jour du code ts du composant pour consolider les abonnements via un TimerObservable:

import { Component, OnDestroy, OnInit } from '@angular/core';
import { MyDataModel } from "../my-data-model";
import { MyExampleService } from "../my-example.service";
import { Observable } from "rxjs";
import { TimerObservable } from "rxjs/observable/TimerObservable";
import 'rxjs/add/operator/takeWhile';

@Component({
  selector: 'app-my-example',
  templateUrl: './my-example.component.html',
  styleUrls: ['./my-example.component.css']
})
export class MyExampleComponent implements OnInit, OnDestroy {
  private data: MyDataModel;
  private display: boolean; // whether to display info in the component
                            // use *ngIf="display" in your html to take
                            // advantage of this

  private alive: boolean; // used to unsubscribe from the TimerObservable
                          // when OnDestroy is called.
  private interval: number;

  constructor(private myExampleService: MyExampleService) {
    this.display = false;
    this.alive = true;
    this.interval = 10000;
  }

  ngOnInit() {
    TimerObservable.create(0, this.interval)
      .takeWhile(() => this.alive)
      .subscribe(() => {
        this.myExampleService.get()
          .subscribe((data) => {
            this.data = data;
            if(!this.display){
              this.display = true;
            }
          });
      });
  }

  ngOnDestroy(){
    this.alive = false; // switches your TimerObservable off
  }
}

= = = modifier = = =

Mon-exemple-service.ts (à l'aide de la HttpClient la Angulaires 5):

import { Injectable } from '@angular/core';
import { HttpClient} from "@angular/common/http";
import { MyDataModel } from "./my-data-model";
import { Observable } from "rxjs";
import 'rxjs/Rx';

@Injectable()
export class MyExampleService {
  private url = 'http://localhost:3000'; // full uri of the service to consume here

  constructor(private http: HttpClient) { }

  get(): Observable<MyDataModel>{
    return this.http
      .get<MyDataModel>(this.url);
  }
}

Notez le changement pour utiliser le HttpClient plutôt que Http (obsolète dans angular5) et la méthode get qui permet d'analyser la réponse dans notre modèle de données sans avoir à utiliser le rxjs .map() de l'opérateur. Alors que le service change pour angular 5, le code du composant reste inchangé.

73
répondu ZackDeRose 2018-04-13 04:59:19

Vous pouvez utiliser la méthode interval de Observable dans Angular2.

import {Component,Input} from 'angular2/core';
import {Observable} from 'rxjs/Rx';

@Component({
  selector: 'my-app',
  template: `
    <div>
      {{message}}
    </div>
  `
})
export class AppComponent {
  constructor() {
    Observable.interval(500)
          .take(10).map((x) => x+1)
          .subscribe((x) => {
            this.message = x;
          }):
  }
}

Voici le plunkr correspondant décrivant ceci: https://plnkr.co/edit/pVMEbbGSzMwSBS4XEXJI?p=preview .

Sur cette base, vous pouvez brancher votre requête HTTP:

initializePolling() {
  return Observable
     .interval(60000)
     .flatMap(() => {
       return this.dataService.getData('url'));
     });
}
31
répondu Thierry Templier 2016-02-10 13:35:58

Je pense que cette réponse n'est plus valide en raison de changements récents de rxjs / observable Vous devez maintenant utiliser IntervalObservable.

Https://github.com/ReactiveX/rxjs/blob/master/src/observable/IntervalObservable.ts

import { IntervalObservable } from 'rxjs/observable/IntervalObservable';

@Component({
  ...
})
export class AppComponent {
  n: number = 0;
  constructor() {
    IntervalObservable.create(1000).subscribe(n => this.n = n);
  }
}
17
répondu Ploppy 2016-11-16 12:03:02

Pour TypeScript (1.8.10 au moment de la réponse) / angular2 (rc1 au moment de la réponse) avec rxjs@5.0.0 (bêta.6 au moment de la réponse), vous devez utiliser le IntervalObservable qui étend la classe Observable

import {IntervalObservable} from 'rxjs/observable/IntervalObservable'

IntervalObservable.create(5000).take(10).map((x) => x + 1)
8
répondu Adam 2016-11-16 12:02:15