API轮询和超时

时间:2018-08-17 11:16:26

标签: angular rxjs observable reactive-programming polling

我有一个轮询用例,其中:

  1. 我想调用一个基于业务逻辑的API,该API立即(1.5-2秒)返回数字(1-10)或错误(API中的网络问题/异常等)。
  2. 如果API返回错误(API中的网络问题/异常等),那么我想取消订阅轮询和显示错误。
  3. 如果API返回成功,我要检查返回值并取消订阅(如果返回值为5)或继续进行轮询。
  4. 我想每5秒调用一次API。
  5. 我要将轮询的最大时间(超时/阈值)保持为3分钟。如果在这3分钟内我没有得到所需的响应(5号),则轮询应该出错。

这是我目前实施的方式:

this.trackSpoke$ = interval(5000)
                .pipe(
                    timeout(250000),
                    startWith(0),
                    switchMap(() =>
                        this.sharedService.pollForAPropertyValue(
                            "newuser"
                        )
                    )
                )
                .subscribe(
                    (data: SpokeProperty) => {
                        this.CheckSpokeStatus(data);
                    },
                    error => {
                        this.trackSpoke$.unsubscribe();
                        this.createSpokeState.CdhResponseTimedOut();
                    }
                );


private CheckSpokeStatus(data) {
        if (data.PropertyValue === "5") {
            this.trackSpoke$.unsubscribe();
            //display success   
        } else {
              //keep the polling going
        }
    }

但是,以上实现并未超时。

需要做些什么才能使它超时并能够实现所有提到的用例?

1 个答案:

答案 0 :(得分:1)

首先使用interval进行API轮询是一种反模式,因为interval不会“等待”您的http请求完成-可能触发多个请求(如果请求需要更多请求然后5s完成)。

我更喜欢将deferrepeatWhendelay结合使用(请参见下面的代码)。

timeout不会触发,因为interval每5s滴答一次,以防止发生超时。 defer / repeatWhen组合也应该解决此问题。

请考虑使用takeWhile为您取消订阅Observable,而不是手动取消订阅。

也不需要在错误处理程序中使用this.trackSpoke$.unsubscribe();,因为在发生错误时会自动取消预订Observable。

this.trackSpoke$ = defer(() => this.sharedService.pollForAPropertyValue("newuser"))
    .pipe(
        timeout(250000),
        repeatWhen(notifications => notifications.delay(5000)),
        takeWhile(data => this.CheckSpokeStatus(data)),
    )
    .subscribe(
        error => {
            this.createSpokeState.CdhResponseTimedOut();
        }
    );


private CheckSpokeStatus(data) {
    return data.PropertyValue !== "5";
}