Rxjs:如果没有结果,请使用更新的参数重试 http 调用
Rxjs : Retry http call with updated parameters if no results
我是 Rxjs 的新手,我正在尝试向我的 API 发出请求,并在参数中传递限制。
我的问题是有时由于某些原因返回的结果是空的。我需要做的是使用更新的参数重试此 API 调用(跳过参数)
pollService.getPoll$(skip, limit).subscribe((pollList) => {
doStuff;
},
(error) => {
doStuff;
});
我阅读了一些关于 RetryWhen RXJS 函数的主题,但它是关于请求失败时的错误,你想重试相同的请求,但我没有错误,我也不知道不想重试相同的请求,我也看到了关于 Replay 函数的主题,但我不是很清楚。
谁能解释一下这里要做什么!!
谢谢
亚历克斯
如果我没理解错的话,您的后端正在使用 skip
和 limit
参数对数据进行分页。
因此,如果您的 skip
值太高,您希望自动降低它。
在 RxJS 中有很多很多方法可以解决这个问题:
- 你可以在
getPoll$
之后插入一个 switchMap
。 SwitchMap
会 return 一个新的 observable,如果可以的话包装结果(使用 of(pollList)
),或者 returning pollService.getPoll$(newSkipValue, newLimitValue)
- 您可以
map
结果并在结果未通过验证时抛出错误。然后你可以 catchError
和 return 新调用 getPoll$
的结果
但是,我建议以不同的方式对调用进行建模。我会使用 Subject
作为请求源,并使用 switchMap
来执行请求。
// inside the component or service
interface GetPollRequest {
skip: number;
limit: number;
}
private _callSource = new Subject<GetPollRequest>();
public triggerCall(skip: number, limit: number) {
this._callSource.next({skip, limit});
}
constructor(...) {
this._callSource.pipe(
// every time _callSource emits, we call the server
switchMap(({skip, limit) => pollService.getPoll$(skip, limit).pipe(
map(pollList => ({ pollList, skip, limit }))
),
tap(({pollList, skip, limit}) => {
// update the request in any way you need. You need to make sure
// that the next automatic trigger doesn't repeat indefinitely,
// or you'll simulate a DOS attack to your backend
if (pollList.length < 2) this.triggerCall(skip - 2, limit);
})
).subscribe(pollList => // update the component status);
}
使用此模式,您将主题用作触发器(或自定义事件,它们几乎相同),并在构造函数期间将它们包装起来。
SwitchMap
用于在每次源发出时创建一个可观察对象(在本例中,执行请求)。
Tap
用于执行一个操作(很像订阅),嵌入在管道内的转换链中。
考虑使用 expand 运算符,如下所示:
import { EMPTY, of } from "rxjs"
import { expand } from "rxjs/operators"
public startPolling(skip: number, limit: number): void {
of([])
.pipe(
expand(x => x.length < 2 ? pollService.getPoll$(skip--, limit) : EMPTY)
)
.subscribe(pollList => {})
}
更新:
public poll = (skip: number, limit: number): void => {
defer(() => getPoll$(1 + skip--, limit))
.pipe(
repeat(),
first(x => {
if(x.length < 2){
// update some variable in the component
return false;
}
return true;
})
)
.subscribe(pollList => { })
}
我是 Rxjs 的新手,我正在尝试向我的 API 发出请求,并在参数中传递限制。 我的问题是有时由于某些原因返回的结果是空的。我需要做的是使用更新的参数重试此 API 调用(跳过参数)
pollService.getPoll$(skip, limit).subscribe((pollList) => {
doStuff;
},
(error) => {
doStuff;
});
我阅读了一些关于 RetryWhen RXJS 函数的主题,但它是关于请求失败时的错误,你想重试相同的请求,但我没有错误,我也不知道不想重试相同的请求,我也看到了关于 Replay 函数的主题,但我不是很清楚。
谁能解释一下这里要做什么!!
谢谢
亚历克斯
如果我没理解错的话,您的后端正在使用 skip
和 limit
参数对数据进行分页。
因此,如果您的 skip
值太高,您希望自动降低它。
在 RxJS 中有很多很多方法可以解决这个问题:
- 你可以在
getPoll$
之后插入一个switchMap
。SwitchMap
会 return 一个新的 observable,如果可以的话包装结果(使用of(pollList)
),或者 returningpollService.getPoll$(newSkipValue, newLimitValue)
- 您可以
map
结果并在结果未通过验证时抛出错误。然后你可以catchError
和 return 新调用getPoll$
的结果
但是,我建议以不同的方式对调用进行建模。我会使用 Subject
作为请求源,并使用 switchMap
来执行请求。
// inside the component or service
interface GetPollRequest {
skip: number;
limit: number;
}
private _callSource = new Subject<GetPollRequest>();
public triggerCall(skip: number, limit: number) {
this._callSource.next({skip, limit});
}
constructor(...) {
this._callSource.pipe(
// every time _callSource emits, we call the server
switchMap(({skip, limit) => pollService.getPoll$(skip, limit).pipe(
map(pollList => ({ pollList, skip, limit }))
),
tap(({pollList, skip, limit}) => {
// update the request in any way you need. You need to make sure
// that the next automatic trigger doesn't repeat indefinitely,
// or you'll simulate a DOS attack to your backend
if (pollList.length < 2) this.triggerCall(skip - 2, limit);
})
).subscribe(pollList => // update the component status);
}
使用此模式,您将主题用作触发器(或自定义事件,它们几乎相同),并在构造函数期间将它们包装起来。
SwitchMap
用于在每次源发出时创建一个可观察对象(在本例中,执行请求)。
Tap
用于执行一个操作(很像订阅),嵌入在管道内的转换链中。
考虑使用 expand 运算符,如下所示:
import { EMPTY, of } from "rxjs"
import { expand } from "rxjs/operators"
public startPolling(skip: number, limit: number): void {
of([])
.pipe(
expand(x => x.length < 2 ? pollService.getPoll$(skip--, limit) : EMPTY)
)
.subscribe(pollList => {})
}
更新:
public poll = (skip: number, limit: number): void => {
defer(() => getPoll$(1 + skip--, limit))
.pipe(
repeat(),
first(x => {
if(x.length < 2){
// update some variable in the component
return false;
}
return true;
})
)
.subscribe(pollList => { })
}