首页 文章

Angular2 http以一定间隔

提问于
浏览
56

我对angular和rxjs很新 . 我正在尝试创建一个angular2应用程序,从静态服务的文本文件(在服务器上本地)获取一些数据,我想检索并在固定时间 interval(5000) 使用Angular2 's http provider and rxjs'映射映射到Datamodel . 反映对服务的txt文件的任何更改 .

使用rxjs 4.x我知道你可以使用 Observable.interval(5000) 来完成这项工作,但它似乎不存在于rxjs 5中 . 我的解决方法当前使用 <meta http-equiv="refresh" content="5" > 刷新整个应用程序,它重新加载整个页面,从而重新加载数据 .

所以我真正想要的是使用observable进行此操作的一些方法,也许是为了检查是否发生了任何更改 . 或者只是重新加载数据 .

任何帮助或其他/更好的方式将非常感谢 .

到目前为止我所拥有的:

@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导入:

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

4 回答

  • 31

    正如@Adam和@Ploppy所提到的,现在不推荐使用Observable.interval(),而不是创建这样的observable的首选方法 . 执行此操作的首选方法是通过IntervalObservable或TimerObservable . [目前在Typscript 2.5.2,rxjs 5.4.3,Angular 4.0.0]

    我想在这个答案中添加一些用法,以证明我在Angular 2框架中找到了最好的方法 .

    首先是你的服务(通过'ng g service MyExample“命令在angular cli中创建) . 假设服务是RESTful(http get request返回一个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
      }
    }
    

    ===编辑===

    更新了组件ts代码以通过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的服务改变时,组件代码保持不变 .

  • 18

    您可以在Angular2中使用 Observableinterval 方法 .

    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'));
         });
    }
    
  • 8

    由于最近rxjs / observable的更改,我认为这个答案不再有效你现在必须使用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);
      }
    }
    
  • 81

    对于TypeScript(答案时为1.8.10)/ angular2(答案时为rc1)和rxjs@5.0.0(答案时为beta.6),您需要使用扩展 Observable 类的 IntervalObservable

    import {IntervalObservable} from 'rxjs/observable/IntervalObservable'
    
    IntervalObservable.create(5000).take(10).map((x) => x + 1)
    

相关问题