我正在使用一个实现长轮询循环的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
处理此案例更优雅的方式?
答案 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;
}
}