完成后n秒重复请求(Angular2 - http.get)

时间:2016-06-21 08:02:12

标签: javascript angular rxjs observable reactivex

我玩了angular2并且在一段时间后卡住了。

使用http.get可以正常处理单个请求,但我想每4秒轮询一次实时数据,经过一段时间的修补并阅读了大量的反应性内容后我最终得到了:

Observable.timer(0,4000)
  .flatMap(
    () => this._http.get(this._url)
       .share()
       .map(this.extractData)
       .catch(this.handleError)
  )
  .share(); 

http.get - observable发出请求结果后,是否有简单方式启动(4秒)间隔? (或者我最终会进入 observable-hell ?)

我想要的时间表:

Time(s): 0 - - - - - 1 - - - - - 2 - - - - - 3 - - - - - 4 - - - - - 5 - - - - - 6
Action:  Request - - Response - - - - - - - - - - - - - - - - - - - -Request-... 
Wait:                | wait for 4 seconds -------------------------> |

4 个答案:

答案 0 :(得分:10)

更新至RxJS 6

import { timer } from 'rxjs';
import { concatMap, map, expand, catchError } from 'rxjs/operators';

pollData$ = this._http.get(this._url)
  .pipe(
    map(this.extractData),
    catchError(this.handleError)
  );

pollData$.pipe(
  expand(_ => timer(4000).pipe(concatMap(_ => pollData$)))
).subscribe();

我使用RxJS 5而且我不确定RxJS 4等效运算符是什么。无论如何这里是我的RxJS 5解决方案,希望它有所帮助:

var pollData = this._http.get(this._url)
            .map(this.extractData)
            .catch(this.handleError);
pollData.expand(
  () => Observable.timer(4000).concatMap(() => pollData)
).subscribe();

expand运算符将发出数据,并以每次发射

递归地启动一个新的Observable

答案 1 :(得分:2)

我自己设法做到了这一点,唯一的缺点就是http.get不能更容易重复。

pollData(): Observable<any> {

  //Creating a subject
  var pollSubject = new Subject<any>();

  //Define the Function which subscribes our pollSubject to a new http.get observable (see _pollLiveData() below)
  var subscribeToNewRequestObservable = () => {
    this._pollLiveData()
      .subscribe(
      (res) => { pollSubject.next(res) }
      );
  };

  //Subscribe our "subscription-function" to custom subject (observable) with 4000ms of delay added
  pollSubject.delay(4000).subscribe(subscribeToNewRequestObservable);

  //Call the "subscription-function" to execute the first request
  subscribeToNewRequestObservable();

  //Return observable of our subject
  return pollSubject.asObservable();

}

private _pollLiveData() {

  var url = 'http://localhost:4711/poll/';

  return this._http.get(url)
    .map(
    (res) => { return res.json(); }
    );
};

以下是您无法使用更直接订阅的原因:

var subscribeToNewRequestObservable = () => {
    this._pollLiveData()
      .subscribe(pollSubject);
  };

完成http.get - 观察也会完成您的主题并阻止其发出更多项目。

这仍然是冷可观察,因此除非您订阅,否则不会提出任何请求。

this._pollService.pollData().subscribe(
  (res) => { this.count = res.count; }
);

答案 2 :(得分:1)

来自Can Nguyen的answer的小修改,以防您希望轮询延迟依赖于之前的请求完成状态。

var pollData = () => request()   // make request
    .do(handler, errorHandler)   // handle response data or error
    .ignoreElements()            // ignore request progress notifications
    .materialize();              // wrap error/complete notif-ns into Notification

pollData()                            // get our Observable<Notification>...
  .expand(                            // ...and recursively map...
    (n) => Rx.Observable              // ...each Notification object...
      .timer(n.error ? 1000 : 5000)   // ...(with delay depending on previous completion status)...
      .concatMap(() => pollData()))   // ...to new Observable<Notification>
  .subscribe();

Plunk

或者:

var pollData = () => request()             // make request
    .last()                                // take last progress value
    .catch(() => Rx.Observable.of(null));  // replace error with null-value

pollData()
  .expand(
    (data) => Rx.Observable
      .timer(data ? 5000 : 1000)           // delay depends on a value
      .concatMap(() => pollData()))
  .subscribe((d) => {console.log(d);});    // can subscribe to the value stream at the end

Plunk

答案 3 :(得分:-1)

如果更方便,您可以尝试使用间隔。调用var client = new System.Net.Http.HttpClient(); var result = client.GetStringAsync("url").Result; 会为您提供subscribe,以便您在一段时间后取消轮询。

Subscription