所以,我已经开始玩rxjs了,我有一个问题,关于在从web服务调用中得到一个错误之后,如何保持我的可观察状态的最佳方法。
const filtro$ = this.estadoPedido.valueChanges.pipe(
distinctUntilChanged(),
tap(_ => {
this._paginaAtual = 0;
this.existemMais = true;
}),
startWith(this.estadoPedido.value),
map(estado => new DadosPesquisa(this._paginaAtual,
this._elemsPagina,
estado,
false))
);
每当select更改时,我都会重置全局页计数器(
tap
startWith
接线员。最后,我将当前状态转换为一个对象,该对象具有加载值所需的所有值。
dataRefresh$ = new Subject<DadosPesquisa>();
这两个可观察对象被合并,这样我就可以有一个单独的路径来调用我的web服务:
this.pedidosCarregados$ = merge(filtro$, this.dataRefresh$).pipe(
tap(() => this.emChamadaRemota = true),
switchMap(info => forkJoin(
of(info),
this._servicoPedidos.obtemPedidos(this._idInstancia,
info.paginaAtual,
info.elemsPagina,
info.estado)
)),
shareReplay(),
tap(([info, pedidos]) => this.existemMais = pedidos.length === info.elemsPagina),
scan((todosPedidos, info) => !info[0].addPedidosToExisting ?
info[1] :
todosPedidos.concat(info[1]), []),
tap(() => this.emChamadaRemota = false),
catchError(erro => {
this.emChamadaRemota = false;
this.trataErro(erro);
this.existemMais = false;
return of([]);
})
);
简单回顾一下我想做的事。。。
水龙头
用于设置和清理控制等待微调器的字段(
emChamadaRemota
)以及控制是否应显示“加载更多”按钮(
existemMais
). 我用的是
forkJoin
switchMap
因为我需要通过管道获取当前搜索的信息。
scan
现在,我还使用了一个拦截器,它负责设置正确的头并用重试策略处理典型错误(401503等)。这是密码
intercept
方法:
intercept(req: HttpRequest<any>, next: HttpHandler): Observable<HttpEvent<any>> {
const headers = this.obtemHeaders();
const requestClonado = req.clone({ headers });
return next.handle(requestClonado).pipe(
retryWhen(this.retryStrategy()),
catchError(err => {
console.error(err);
let msgErro: string;
if(err instanceof HttpErrorResponse && this._servicoAutenticacao.trataErroFimSessao(err)) {
msgErro = "A sua sessão terminou. Vai ser redirecionado para a página de login" ;
}
else if(err.status === 503 ) {
msgErro = "O servidor não devolveu uma resposta válida (503).";
}
else {
msgErro = err.error && err.error.message ? err.error.message : "Ocorreu um erro no servidor.";
}
if(err.status !== 503) {
this._logger.adicionaInfoExcecao(msgErro).subscribe();
}
return throwError(msgErro);
}
));
}
我读过一些文章,其中提到解决方案是创建一个内部的observable,它从不抛出,并封装从web服务调用返回的observable。走这条路吗?如果是的话,我能在拦截器级别上做吗?或者,在发生错误的情况下,我是否应该简单地重建我的可观察链(但不使用startWith操作符自动启动)?