我在 angular 应用程序中有一个菜单,这个菜单控制我的 Web 应用程序中选定的客户端。
因为它是:
这似乎是一个不错的设计,但是在基于客户端创建新的 observables 时我遇到了一些问题(从未完成 observables)。AFAIK 这是由于第一个 observable 永远不会完成并且此属性将传播。
//Command
export interface Command {
productName: string;
qty: number;
}
//The service
@Injectable()
export class ClientService {
private _client: ReplaySubject<Client> = new ReplaySubject(1);
setClient(client: Client) { // The menu component calls setClient on a user click
this._client.next(client);
}
getClient(): Observable<Client> { // getClient is heavilly called in child component to observe client selection events.
return this._client.asObservable();
}
}
getCommands(): Observable<Command> { //Used in a template with async pipe
//In a child component
const commandsObs = this.clientService.getClient()
//.take(1) //I am forced to use take(1) to get getCommands() observer to complete
.flatMap(c => {
return Observable.merge(getCommandsPromise1(c), getCommandsPromise2(c));
})
.reduce((acc, next) => Object.assign({}, acc, next))
.map(next => {
return finishMakingCommand(next));
})
.catch(err => /* Some error management code*/)
}
getCommandsPromise1(client: Client): Promise<any> {
//REST call returning a promise
return Promise.resolve({ 'command1': { 'productName': 'toy', qty: 1 } });
}
getCommandsPromise2(client: Client): Promise<any> {
//REST call returning a promise
return Promise.resolve({ 'command2': { 'productName': 'another toy', qty: 1 } });
}
finishMakingCommand(commands: any): Command[] {
// Flattens 'command1' and 'command2' to a list of commands
return [{'productName': 'toy', qty: 1}, {'productName': 'another toy', qty: 2}];
}
我想知道更有经验的开发人员是否认为永无止境的 observable 是一个好的设计,以及有哪些替代方案可以避免永无止境的 observables。
正如我上面提到的,将 observables 视为铺设管道。唯一出现问题的时候是水不断涌来(就像Observable.interval(1000)
水源一样——它会一直滴答作响)。在这种情况下,如果您手动订阅 observable,您还需要取消订阅。
但是,正如您所说,您使用的是异步管道,而 Angular 负责取消订阅。
通过单击菜单,一键将发送一个值。可观察对象永远不会完成(即永远不会收到完成的事件)是很常见的,这不是必需的。
Completed 事件对于聚合操作符通常很有用,例如toArray()
让他们知道整个值集。
我建议只使用
const commandsObs = this.clientService.getClient();
并在模板中(示例)
<div>{{ commandObs | async }}</div>
忘记 flatMap,除非它打算做一些花哨的事情 - 让我知道。
编辑 - 对新示例代码的建议更改
您可以尝试在 flatmap 内移动 reduce 和 map,因为它们旨在处理内部 observable (Observable.merge) 的结果。
const commandsObs = this.clientService.getClient()
.flatMap(c => {
return Observable.merge(getCommandsPromise1(c), getCommandsPromise2(c))
.reduce((acc, next) => Object.assign({}, acc, next))
.map(next => finishMakingCommand(next) )
});
尝试的替代版本,
const commandsObs = this.clientService.getClient()
.map(c => Observable.forkJoin(getCommandsPromise1(c), getCommandsPromise2(c) );
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句