在我的应用中,如果表单中的任何数据尚未完成加载,我希望“保存”按钮不执行任何操作。我表单中的数据源都是Observables
:source1$
和source2$
由于用户可以随时单击按钮,因此我希望能够检查是否有任何Web API请求处于挂起状态,然后它们什么也不做-否则保存。
我在想像这样的东西:
saveButton_onClicked() {
if (// source1$ and source2$ are completed) {
this.saveForm();
}
}
在任何时候,可以将这些可观察变量中的任何一个分配给新的可观察变量(例如,刷新数据时),并且我认为forkJoin
在这里不起作用,因为我需要知道实时 (无论是否保存表单),我都不希望click事件正在等待可观察到的forkJoin
的解决。
有什么想法吗?
答案 0 :(得分:3)
实际上,我认为最简单的方法是使用forkJoin
和finalize
运算符,而不是检查源Observable本身,而是创建一个属性。 loading
,您可以随时检查并查看是否有待处理的Observable:
whatever() {
this.loading = true;
forkJoin(source1$, source2$)
.pipe(
finalize(() => this.loading = false)
)
.subscribe();
}
saveButton_onClicked() {
if (!this.loading) {
...
}
}
答案 1 :(得分:1)
嗯,有很多方法可以给猫皮。
有些比其他的更优雅。我希望将额外的可观察属性的数量保持最小,在这种情况下,该数量应该为2。我将添加属性isRunningRequest$
,该属性的发射值是一个标志,如果当前正在运行操作,则为true。通过在另一个可观察到的asyncAction$
上的聚合,可以使该标志变得生动起来,以用于跟踪当前正在运行的动作:
export class AsyncActionData {
actionType: 'start' | 'end';
actionToken: string;
}
public asyncAction$ = new Subject<AsyncActionData>();
public isRunningRequest$ = new BehaviorSubject<boolean>(false);
constructor(...) {
this.asyncAction$
.pipe(
// we keep an array of currently running actions, and add
// or remove from the array according to the action type
scan((arr: string[], action: AsyncActionData) => {
return action.actionType === 'start'
? arr.concat(action.actionToken)
: arr.filter(action => action !== action.actionToken);
}, []),
map(arr => arr.length === 0 ? false : true)
)
.subscribe(requestsAreRunning => this.isRunningRequest$.next(requestsAreRunning));
}
执行操作时,您会在asyncAction$
上发出事件:
this.asyncAction$.next({actionType: 'start', actionToken: 'action1'});
this.http.post(...)
.subscribe(result => ...,
null,
() => this.asyncAction$.next({actionType: 'end', actionToken: 'action1'})
);
(所有代码都未经测试,但是应该是正确的)