问题
I have a polling use-case where:
- I want to call an API that, based on business logic, returns numbers(1-10) or error (network issue/ exception in API etc..) instantly (1.5-2 sec).
- If the API returns an error (network issue/ exception in API etc..) then I want to unsubscribe the polling and display error.
- If the API returns success, I want to check the return value and un-subscribe(if the return value is 5) or keep the polling going.
- I want to call API every 5 sec.
- I want to keep the max time(timeout/threshold) for the polling as 3mins. If I don't get the desired response(number 5) in these 3mins, the polling should error out.
This is how I have implemented it currently:
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
}
}
But, the above implementation is not timing out.
What needs to be done so that it times out and I am able to achieve all mentioned use-case?
回答1:
First of all using interval
for API polling is quite an anti-pattern because interval
won't "wait" for your http request to finish - potentially triggering multiple requests (if the request takes more then 5s to complete).
I prefer to use defer with repeatWhen and delay
(see the code below).
The timeout
is not triggering because the interval
is ticking every 5s preventing the timeout from ever occurring. The defer
/repeatWhen
combo should also fix that.
Instead of manually unsubscribing consider using takeWhile to unsubscribe the Observable for you.
Also using this.trackSpoke$.unsubscribe();
in the error handler is not needed because Observable is unsubscribed automatically in case of an error.
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";
}
来源:https://stackoverflow.com/questions/51894239/api-polling-and-timeout