问题描述
我对 angular 和 rxjs 很陌生.我正在尝试创建一个 angular2 应用程序,它从静态提供的文本文件(本地服务器上)获取一些数据,我想使用 Angular2 的 http 提供程序和 rxjs 的地图在固定时间检索并映射到数据模型 interval(5000)
.反映对提供的 txt 文件的任何更改.
I am quite new to angular and rxjs.I am trying to create an angular2 app that gets some data from staticly served text file(Locally on server), which I would like to retrieve and map to Datamodel using Angular2's http provider and rxjs's map at a fixed time interval(5000)
. To reflect any changes to the served txt file.
使用 rxjs 4.x 我知道你可以使用 Observable.interval(5000)
来完成这项工作,但它似乎不存在于 rxjs 5 中.我的解决方法目前使用 <meta http-equiv="refresh" content="5" >
刷新整个应用程序,这会重新加载整个页面,从而重新加载数据.
With rxjs 4.x I know you could use Observable.interval(5000)
to do the job, but it does not seem to exist in rxjs 5.My workaround currently refresh the whole application using <meta http-equiv="refresh" content="5" >
Which reloads the whole page, and thus reloads the data.
所以我真正想要的是某种方式来使用 observables 来完成这项工作,也许是为了检查是否发生了任何变化.或者只是重新加载数据.
So what I would really like is some way to do this working with observables, maybe to check if any changes have happened. or just to reload the data anew.
非常感谢任何帮助或其他/更好的方法.
Any help or other/better way will be very much appreciated.
到目前为止我所拥有的:
What I have so far:
@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("
");
})
.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: 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 导入:
index.html imports:
<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>
推荐答案
正如@Adam 和@Ploppy 所提到的,Observable.interval() 现在被 不是创建这种可观察对象的首选方式.这样做的首选方法是通过 IntervalObservable 或 TimerObservable.[目前在 Typscript 2.5.2、rxjs 5.4.3、Angular 4.0.0]
As @Adam and @Ploppy mentioned, the Observable.interval() is now 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]
我想在这个答案中添加一些用法,以演示我在 Angular 2 框架中找到的最佳方法.
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.
首先你的服务(通过'ng g service MyExample"命令在angular cli中创建)假设服务是RESTful(http get请求返回一个json):
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
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());
}
}
*** 查看 Angular 5 服务的底部更新 ***
*** see bottom updates to service for Angular 5 ***
现在你的组件代码('ng g component MyExample'):
Now your component code ('ng g component MyExample'):
my-example.component.ts:
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
}
}
=== 编辑 ===
更新了组件 ts 代码以通过 TimerObservable 合并订阅:
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
}
}
=== 编辑 ===
my-example-service.ts(使用 HttpClient 和 Angular 5):
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);
}
}
注意更改为使用 HttpClient 而不是 Http(在 angular5 中已弃用)和 get 方法,该方法允许将响应解析到我们的数据模型中,而无需使用 rxjs .map() 运算符.虽然 angular 5 的服务发生了变化,但组件代码保持不变.
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.
这篇关于如何每隔一段时间发出HTTP请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!