Javascript 角度RxJS-设置值将管道值更改为null,直到可观察到的值被解析
我正试图通过管道从Javascript 角度RxJS-设置值将管道值更改为null,直到可观察到的值被解析,javascript,angular,typescript,rxjs,Javascript,Angular,Typescript,Rxjs,我正试图通过管道从选择来触发相应的API请求,并在未收到响应时显示微调器。除此之外,我还尝试使用publish()和refCount(),这样我就可以在模板中的多个位置使用async管道的可观察性 my component.ts my component.html 然后它就可以正常工作了,只需要向服务器发出一个fire's off 1请求。但当您更改select选项时,results$|async在新值可用之前不再计算为null。相反,它坚持使用旧的值,然后突然用更新的值替换它。理想情况下,
选择来触发相应的API请求,并在未收到响应时显示微调器。除此之外,我还尝试使用publish()
和refCount()
,这样我就可以在模板中的多个位置使用async
管道的可观察性
my component.ts
my component.html
然后它就可以正常工作了,只需要向服务器发出一个fire's off 1请求。但当您更改select选项时,results$|async
在新值可用之前不再计算为null
。相反,它坚持使用旧的值,然后突然用更新的值替换它。理想情况下,您希望分离变量-以便上下文更清楚-加载的状态和最终的结果是两件不同的事情。假设结果
为空
等同于状态
正在加载可能是危险的,因为它们根本不同。例如,如果出现错误会发生什么?这意味着结果
为空,但状态
不再加载。如果遵循您的实现,当抛出错误时,您的微调器将永远处于加载状态。而且它也可能会运行到您描述的场景中-您失去了加载的状态,因为现在它不再是空的,并且您的微调器在第一个初始请求之后将永远不会加载
每次更改表单时,将结果
重置为null
也有点多余(毫无意义)。从技术上讲,您的结果不是null
。它有结果。只是结果不是最新的
相反,请使用主题来发射值:
private isLoading = new BehaviourSubject<boolean>(false);
并让您的html绑定到它:
<mat-progress-spinner *ngIf="isLoading"></mat-progress-spinner>
让我把你的问题答对。您希望:当您更改选择选项时,results$|async
应更改为null
,直到新值可用?是的,这是正确的。尝试使用(results)?.name
?isLoading
不能是私有的,我们应该绑定到isLoading | async
。但这根本不会触发请求,因为使用results$
的div将具有*ngIf=“!load”
。因此,没有人订阅结果$
。我尝试使用*ngIf=“(results$| async)&&&&!loading”
,这会触发请求,但我得到错误无法再次读取null的属性“name”
。同意您的“关注点分离”参数。顺便说一句,“冗余”和“无意义”并不像您所建议的那样是同义词。在重新加载结果时将其重置为null既不是多余的,也不是毫无意义的,这取决于需求。
<mat-progress-spinner *ngIf="!(results$ | async)"></mat-progress-spinner>
<div *ngIf="(results$ | async) as results">
<p>Name {{(results).name}}</p>
<small>{{(results).description}}
</div>
private isLoading = new BehaviourSubject<boolean>(false);
this.results$ = this.selectControl.valueChanges.pipe(
startWith('hard'),
tap(() => this.isLoading.next(true)), //sets loading to true, we are firing our api request!
switchMap((evalStrategy: 'hard' | 'soft') => this.apiService.getResults(evalStrategy)),
tap(() => this.isLoading.next(false)), //api finished fetching, stop the spinner!
catchError(() => this.isLoading.next(false)), //this is up to you on how you want to do error handling.
publish(),
refCount(),
);
<mat-progress-spinner *ngIf="isLoading"></mat-progress-spinner>