Angular2 + http w odstępie

Jestem całkiem nowy w angular i rxjs. Próbuję stworzyć aplikację angular2, która pobiera dane ze statycznie serwowanego pliku tekstowego (lokalnie na serwerze), który chciałbym pobrać i zmapować do Datamodel za pomocą dostawcy http Angular2 i mapy rxjs w ustalonym czasie interval(5000). Aby odzwierciedlić wszelkie zmiany w serwowanym pliku txt.

Z rxjs 4.x wiem, że możesz użyć Observable.interval(5000) do wykonania tej pracy, ale wydaje się, że nie istnieje w rxjs 5. Moje obejście aktualnie odświeża całą aplikację za pomocą <meta http-equiv="refresh" content="5" > Który przeładowuje całą stronę, a tym samym przeładowuje dane.

Więc to, co naprawdę chciałbym, to jakiś sposób, aby to zrobić, pracując z obserwowalnymi, być może, aby sprawdzić, czy jakieś zmiany zaszły. lub po prostu przeładować dane na nowo.

Każda pomoc lub inny / lepszy sposób będą bardzo mile widziane.

Co mam do tej pory:

@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")
        );
    }
}

Zależności: pakiet.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"
}

Indeks.import 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>
Author: mxr7350, 2016-02-10

4 answers

Jak wspomniali @Adam i @Ploppy, obserwowalne.interval() jest obecnie przestarzałe nie jest preferowanym sposobem tworzenia takiej obserwowalnej. Preferowanym sposobem jest użycie IntervalObservable lub TimerObservable. [obecnie w Typscript 2.5.2, rxjs 5.4.3, Angular 4.0.0]

Chciałem dodać trochę użycia do tej odpowiedzi, aby zademonstrować, co znalazłem najlepszy sposób na zrobienie tego w frameworku Angular 2.

Najpierw Twój serwis (utworzony w angular cli za pośrednictwem ' ng g service Myexample " polecenie). Przy założeniu, że usługa jest RESTful (http get request zwraca json):

Mój-przykład.obsługa.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());
  }
}

*** Zobacz u dołu aktualizacje serwisu kątowa 5 * * *

Teraz Twój kod komponentu ('ng g component MyExample'):

Mój-przykład.komponent.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
  }
}

=== edit = = =

Zaktualizowano kod komponentu ts, aby skonsolidować subskrypcje za pomocą 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
  }
}

=== edit = = =

My-example-service.ts (za pomocą HttpClient a la Angular 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);
  }
}

Uwaga zmiana użycia HttpClient zamiast Http (przestarzałe w angular5) oraz metody get, która pozwala na parsowanie odpowiedzi do naszego modelu danych bez konieczności stosowania rxjs .operator map (). Podczas gdy usługa zmienia się dla angular 5, kod komponentu pozostaje niezmieniony.

 73
Author: ZackDeRose,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-13 04:59:19

Możesz użyć interval metody Observable w obrębie Kąta2.

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;
          }):
  }
}

Oto odpowiedni plunkr opisujący to: https://plnkr.co/edit/pVMEbbGSzMwSBS4XEXJI?p=preview .

Na tej podstawie możesz podłączyć żądanie HTTP:

initializePolling() {
  return Observable
     .interval(60000)
     .flatMap(() => {
       return this.dataService.getData('url'));
     });
}
 31
Author: Thierry Templier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-10 13:35:58

Myślę, że ta odpowiedź nie jest już ważna ze względu na ostatnie zmiany rxjs / observable Teraz musisz użyć 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
Author: Ploppy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-16 12:03:02

Dla maszynopisu (1.8.10 w momencie odpowiedzi) / angular2 (rc1 w momencie odpowiedzi) z [email protected] (beta.6 w momencie odpowiedzi) musisz użyć IntervalObservable, która rozszerza Observable klasę

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

IntervalObservable.create(5000).take(10).map((x) => x + 1)
 8
Author: Adam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-16 12:02:15