如何使用RXJS Observables轮询服务?

20

如何修改以下代码,使得get请求“api/foobar”每500毫秒重复一次?

import {Observable} from "RxJS/Rx";
import {Injectable} from "@angular/core";
import {Http} from "@angular/http";

@Injectable() export class ExampleService {
    constructor(private http: Http) { }

    getFooBars(onNext: (fooBars: FooBar[]) => void) {
        this.get("api/foobar")
            .map(response => <FooBar[]>reponse.json())
            .subscribe(onNext,
                   error => 
                   console.log("An error occurred when requesting api/foobar.", error));
    }
}

我在这里回答了一个类似的问题https://dev59.com/EJ_ha4cB1Zd3GeqP4suM#42659054,事实上我没有使用`interval`,因为如果您的调用需要超过500毫秒,另一个调用将被触发。我的答案解决了这个问题 :) - maxime1992
3个回答

41

请确保您已从 rxjs/Rx 导入了 {Observable}。如果我们没有导入,有时会出现“未找到可观察对象”的错误。

工作 plnkr http://plnkr.co/edit/vMvnQW?p=preview

import {Component} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/Rx';
import {Observable} from 'rxjs/Rx';

@Component({
    selector: 'app',
    template: `
      <b>Angular 2 HTTP polling every 5 sec RxJs Observables!</b>
      <ul>
        <li *ngFor="let doctor of doctors">{{doctor.name}}</li>
      </ul>

      `
})

export class MyApp {
  private doctors = [];
  pollingData: any;      

  constructor(http: Http) {
   this.pollingData = Observable.interval(5000)
    .switchMap(() => http.get('http://jsonplaceholder.typicode.com/users/')).map((data) => data.json())
        .subscribe((data) => {
          this.doctors=data; 
           console.log(data);// see console you get output every 5 sec
        });
  }

 ngOnDestroy() {
    this.pollingData.unsubscribe();
}
}

14
这可能很危险 - 如果请求的时间超过5000,下一次switchMap运行时,它将取消先前的请求。因此,如果您所有的请求都需要超过5000的时间,那么每个请求都将取消下一个请求,您将无法获取任何轮询结果。 (5000是比较安全的时间,但500太短了) - Rusty Rob
8
如果您担心请求时间过长,可以使用concatMap,它将跟踪每个请求并按正确的顺序处理它们。 - GFoley83
12
如果你不想等待5秒钟来获取第一条数据:.interval(5000).startWith(0) - Jonas Wyss
1
它的运行很好,但当API出现错误时,整个间隔都会中断。 - ideeps
1
@ideep 尝试在 subscribe 的 err 参数中捕获您的错误。我忘记在 subscribe 中添加 error 参数了。 - Amit kumar
显示剩余2条评论

3

试试这个

return Observable.interval(2000) 
        .switchMap(() => this.http.get(url).map(res:Response => res.json()));

谢谢您的回复。这对我来说似乎也可以工作。然而,我遇到了这个错误:EXCEPTION: Observable_1.Observable.interval is not a function。我正在使用 RxJS 版本 5-beta。是否有可能回滚到版本 4 可以解决这个问题? - Jerry Huckins
我猜你可以在 package.json 文件中实现。 - Rahul Singh

-4

为什么不尝试使用setInterval()呢?

setInterval(getFooBars(), 500);

2
为什么这个答案被踩了?像我这样的读者会对为什么这个答案被评为“差劲”感兴趣。 - Francisco C.
6
这个回答被downvote了,因为它使用了定期轮询而不是可观察模式。问题是如何使用轮询机制和可观察对象。此外,使用setInterval方法将强制执行 getFooBars 函数并每500毫秒触发API请求,无论是否已返回响应。而使用可观察对象,当再次触发同一API时,可以取消执行API。 - yaloumi
如果你正在使用AngularJS,那么这是一个不错的解决方案,但对于Angular+来说,最好使用Observable方法。 - Julian Torregrosa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接