How to make HTTP request at an interval?
As @Adam and @Ploppy mentioned, the Observable.interval() is now deprecated not the preferred way of creating such an observable. The preferred way of doing this is via the IntervalObservable or TimerObservable.
[currently in Typscript 2.5.2, rxjs 5.4.3, Angular 4.0.0]
I wanted to add some usage to this answer to demonstrate what I found the best way of doing this in the Angular 2 framework.
First your service (created in angular cli via the 'ng g service MyExample" command). Assuming the service is RESTful (http get request returns a json):
my-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());
}
}
*** see bottom updates to service for Angular 5 ***
Now your component code ('ng g component MyExample'):
my-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
}
}
=== edit ===
Updated the component ts code to consolidate the subscriptions via a 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 (using the 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);
}
}
Note change to use the HttpClient rather than Http (deprecated in angular5) and the get method which allows for parsing the response into our data model without having to employ the rxjs .map() operator. While the service changes for angular 5, the component code remains unchanged.
You can use the interval
method of Observable
within 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;
}):
}
}
Here is the corresponding plunkr describing this: https://plnkr.co/edit/pVMEbbGSzMwSBS4XEXJI?p=preview.
Based on this, you can plug your HTTP request:
initializePolling() {
return Observable
.interval(60000)
.flatMap(() => {
return this.dataService.getData('url'));
});
}
I think this answer is not valid anymore due to recent changes of rxjs/observable You now have to use 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);
}
}