Angular9订阅失败如何重试?
How to retry a subscription when it fails in Angular 9?
上下文: 使用 Angular 9. 我正在等待后端可以接收请求。同时不是,有进度条loading。
问题:当后端还未可用时,订阅立即失败并进入方法.subscribe()
的(错误)回调函数,带有类似 Http failure response for http://localhost:5555/api/info: 504 Gateway Timeout
的消息
我做了一些研究,我发现的示例修改了服务 class,其中 httpClient.get
存在,以重试 x 次请求,但我不能这样做ts 服务是自动生成的。
我的第一个想法是使用 while() 循环和一个标志,因此每次执行 (error) 时,标志都会为 false,然后重试订阅。但是会导致内存泄漏。
checkIfBackendAvailable() {
var backendAvailable = false;
while(!backendAvailable){
let subscription = this.infoService.getInfo().subscribe(
(info) => {
if (info) {
backendAvailable = true;
this.progressBarValue = 100
// do somethings
}
}
,
(error) => {
clearTimeout(this.infoTimeOut);
this.showMessage("back-end not available");
this.stopLoadingBar();
//do somethings
}
);
}
this.infoTimeOut = setTimeout(() => {
if (!backendAvailable) {
subscription.unsubscribe()
this.showMessage("error");
this.stopLoadingBar();
}
}, 120000);
}
请试试这个方法。使用来自 rxjs/operators.
的 rxjs retry()
您仍然可以使用 retry
或 retryWhen
可观察运算符,只要您的服务功能 returns Observable
.
使用retry
:
this.infoService.getInfo()
.pipe(
retry(3), // you retry 3 times
delay(1000) // each retry will start after 1 second,
)
.subscribe(res => {
// success
})
使用retryWhen
:
this.infoService.getInfo()
.pipe(
retryWhen(errors => errors.pipe(
// define conditions for retrying with some of observable operators
)),
)
.subscribe(res => {
// success
})
这是最接近我想要的解决方案:
checkBackend() {
console.log('Waiting for backend...');
let infoObservable = this.infoService.getInfo().pipe(
retryWhen(errors =>
errors.pipe(
delay(10000),
tap(errorStatus => {
//stop timeout if error
this.stopInfoTimeOut();
//parse the error, depending on the return from the http.get
if (!errorStatus.includes('504')) {
throw errorStatus;
}
//run timeout when trying a new request
this.runInfoTimeout();
})
)
))
this.infoSubscription= infoObservable.subscribe({
next: val => {
if (val) {
console.log('Backend available');
this.stopInfoTimeOut();
}
},
error: val => {
console.log(val);
this.stopInfoTimeOut();
this.showMessage("Backend not available, try later");
},
complete: () => {}
})
this.runInfoTimeout();
}
stopInfoTimeOut(){
clearTimeout(this.infoTimeOut);
}
runInfoTimeout(){
//timeout for non error requests, waiting to be answered
this.infoTimeOut =setTimeout(() => {
console.log("Backend response time out");
this.infoSubscription.unsubscribe()
this.showMessage("Backend not available, try later");
}, 120000);//2 min
}
上下文: 使用 Angular 9. 我正在等待后端可以接收请求。同时不是,有进度条loading。
问题:当后端还未可用时,订阅立即失败并进入方法.subscribe()
的(错误)回调函数,带有类似 Http failure response for http://localhost:5555/api/info: 504 Gateway Timeout
我做了一些研究,我发现的示例修改了服务 class,其中 httpClient.get
存在,以重试 x 次请求,但我不能这样做ts 服务是自动生成的。
我的第一个想法是使用 while() 循环和一个标志,因此每次执行 (error) 时,标志都会为 false,然后重试订阅。但是会导致内存泄漏。
checkIfBackendAvailable() {
var backendAvailable = false;
while(!backendAvailable){
let subscription = this.infoService.getInfo().subscribe(
(info) => {
if (info) {
backendAvailable = true;
this.progressBarValue = 100
// do somethings
}
}
,
(error) => {
clearTimeout(this.infoTimeOut);
this.showMessage("back-end not available");
this.stopLoadingBar();
//do somethings
}
);
}
this.infoTimeOut = setTimeout(() => {
if (!backendAvailable) {
subscription.unsubscribe()
this.showMessage("error");
this.stopLoadingBar();
}
}, 120000);
}
请试试这个方法。使用来自 rxjs/operators.
的 rxjs retry()您仍然可以使用 retry
或 retryWhen
可观察运算符,只要您的服务功能 returns Observable
.
使用retry
:
this.infoService.getInfo()
.pipe(
retry(3), // you retry 3 times
delay(1000) // each retry will start after 1 second,
)
.subscribe(res => {
// success
})
使用retryWhen
:
this.infoService.getInfo()
.pipe(
retryWhen(errors => errors.pipe(
// define conditions for retrying with some of observable operators
)),
)
.subscribe(res => {
// success
})
这是最接近我想要的解决方案:
checkBackend() {
console.log('Waiting for backend...');
let infoObservable = this.infoService.getInfo().pipe(
retryWhen(errors =>
errors.pipe(
delay(10000),
tap(errorStatus => {
//stop timeout if error
this.stopInfoTimeOut();
//parse the error, depending on the return from the http.get
if (!errorStatus.includes('504')) {
throw errorStatus;
}
//run timeout when trying a new request
this.runInfoTimeout();
})
)
))
this.infoSubscription= infoObservable.subscribe({
next: val => {
if (val) {
console.log('Backend available');
this.stopInfoTimeOut();
}
},
error: val => {
console.log(val);
this.stopInfoTimeOut();
this.showMessage("Backend not available, try later");
},
complete: () => {}
})
this.runInfoTimeout();
}
stopInfoTimeOut(){
clearTimeout(this.infoTimeOut);
}
runInfoTimeout(){
//timeout for non error requests, waiting to be answered
this.infoTimeOut =setTimeout(() => {
console.log("Backend response time out");
this.infoSubscription.unsubscribe()
this.showMessage("Backend not available, try later");
}, 120000);//2 min
}