没有Rx.interval

时间:2018-06-08 19:42:31

标签: angular rxjs

我正在使用一个实现长轮询循环的API,因为在服务器中保持连接打开一段任意时间(比如介于0和5之间),然后在有新消息时立即返回响应发送。

目前,我的代码每5秒发送一次请求,无论服务器何时响应。 如果连续有3个请求,并且服务器以[1s,2s,3s]响应,那么当前我将发送3个请求[5s,5s,5s]总共~15s,理想情况下我希望它全部发生在6s(1 + 2 + 3)。

Rx.interval(5000)
  .pipe(
    Rx.concatMap(() => httpClient.get('/api/messages')),
    retry(8000)
   )
  .subscribe((data) => handleResponse(data));

如果这是一个承诺,我会写一些诸如

之类的东西
const fetchRequest = httpClient.get('/api/messages').toPromise()
  .then(data => {handleResponse(data); fetchRequest()});

但在我的情况下,我需要最终返回一个Obvservable。

从阅读RxJS文档开始,似乎最接近我想要的是retryWhen,它会起作用,但在我看来语义错误,因为它会迫使我提出Error保持循环。

httpClient.get('/api/messages')),
  .subscribe((data) => {
    handleResponse(data);
    throw 'keep going';
  })
  .retryWhen(val => val === 'keep going')

是否有比使用retryWhen处理此案例更优雅的方式?

1 个答案:

答案 0 :(得分:1)

根据我的理解,您希望向服务器发送请求,并在收到响应后,再次发送新请求。

StackBlitz live demo for this code

这是该行为的示例。

import { Observable, Subject, of } from 'rxjs';
import { switchMap, delay, startWith, tap, concatMap } from 'rxjs/operators';

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  subject = new Subject();

  constructor() {

    this.subject.pipe(
      startWith({}),
      concatMap(() => this.testGet()),
      tap(() => this.subject.next()),
    ).subscribe(x => {
      console.log('inside subscribe', x);
    })

  }

  async testGet() {
    console.log('start get');
    await of({}).pipe(delay(2000)).toPromise();
    console.log('finish get');
    return null;
  }
}