Подтвердить что ты не робот

Angular2 + http с интервалом

Я довольно плохо знаком с angular и rxjs. Я пытаюсь создать приложение angular2, которое получает некоторые данные из статически обслуживаемого текстового файла (локально на сервере), который я хотел бы получить и отобразить на Datamodel с помощью http-провайдера Angular2 и карты rxjs через фиксированный interval(5000). Чтобы отразить любые изменения в обслуживаемом текстовом файле.

В rxjs 4.x я знаю, что вы можете использовать Observable.interval(5000) для выполнения этой работы, но, похоже, его нет в rxjs 5. Мой обходной путь в настоящее время обновляет все приложение с использованием <meta http-equiv="refresh" content="5" > Который перезагружает всю страницу и таким образом перезагружает данные.

Так что мне бы очень хотелось, чтобы это был какой-то способ работы с наблюдаемыми, возможно, чтобы проверить, произошли ли какие-либо изменения. или просто перезагрузить данные заново.

Любая помощь или другой/лучший способ будет очень признателен.

Что у меня так далеко:

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

Зависимости: package.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.html import:

<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>
4b9b3361

Ответ 1

Как упоминали @Adam и @Ploppy, Observable.interval() теперь не рекомендуется, а не является предпочтительным способом создания такой наблюдаемой. Предпочтительный способ сделать это через IntervalObservable или TimerObservable. [в настоящее время в Typscript 2.5.2, rxjs 5.4.3, Angular 4.0.0]

Я хотел добавить немного использования в этот ответ, чтобы продемонстрировать, как я нашел лучший способ сделать это в среде Angular 2.

Сначала ваш сервис (созданный в angular cli с помощью команды 'ng g service MyExample "). Предполагается, что сервис RESTful (запрос http get возвращает json):

мой-example.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());
  }
}

*** смотрите нижние обновления к сервису для Angular 5 ***

Теперь ваш код компонента ('ng g component MyExample'):

мой-example.component.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
  }
}

=== редактировать ===

Обновлен код компонента для объединения подписок с помощью 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
  }
}

=== редактировать ===

my-example-service.ts (используя HttpClient в стиле 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);
  }
}

Заметьте, что измените использование HttpClient вместо Http (устарело в angular5) и метода get, который позволяет анализировать ответ в нашей модели данных без использования оператора rxjs.map(). В то время как услуга изменяется на угловую 5, код компонента остается неизменным.

Ответ 2

Вы можете использовать метод interval Observable в пределах 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;
          }):
  }
}

Вот соответствующий plunkr, описывающий это: https://plnkr.co/edit/pVMEbbGSzMwSBS4XEXJI?p=preview.

На основании этого вы можете подключить свой HTTP-запрос:

initializePolling() {
  return Observable
     .interval(60000)
     .flatMap(() => {
       return this.dataService.getData('url'));
     });
}

Ответ 3

Я думаю, что этот ответ больше недействителен из-за недавних изменений rxjs/наблюдаемых Теперь вам нужно использовать 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);
  }
}

Ответ 4

Для TypeScript (1.8.10 во время ответа)/ angular2 (rc1 во время ответа) с [email protected] (бета-версия 6 во время ответа) вам нужно использовать IntervalObservable который расширяет класс Observable

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

IntervalObservable.create(5000).take(10).map((x) => x + 1)

Ответ 5

это можно легко сделать через switchMap

Observable.timer(0, 5000)
          .switchMap((t) =>
            this.http.get(...).pipe(
                catchError(...)
            )
          )
          .subscribe(...)

Ответ 6

Отказ от ответственности: это было первоначально редактирование для другого ответа, но содержит слишком много изменений.

Это может быть легко сделано через switchMap:

Observable.timer(0, 5000)
  .switchMap(() => this.http.get(...).pipe(...)
  .subscribe(...)

Или в синтаксисе RxJS 6:

import { timer } from 'rxjs';
import { switchMap } from 'rxjs/operators';

timer(0, 5000) // repeats every 5 seconds
  .pipe(switchMap(() => this.http.get(...).pipe(...))
  .subscribe(...);

Вы даже можете использовать interval вместо timer:

import { interval } from 'rxjs';
import { switchMap } from 'rxjs/operators';

interval(5000) // repeats every 5 seconds
  .pipe(switchMap(() => this.http.get(...).pipe(...))
  .subscribe(...);