【发布时间】:2019-12-18 17:49:50
【问题描述】:
我正在使用 TypeScript、Angular、NGRX 应用程序。我一直在编写状态可观察对象而不使用选择器——主要原因是我发现它们不如直接使用 RxJS 运算符强大。例如,不能单独使用选择器来限制事件的发射 - 而是必须使用过滤运算符。
在大多数情况下,用 observables 替换选择器没有任何问题 - observables 可以以与选择器相同的方式组成 - 除了一个例外:我不知道如何组成 observables 可能由相同的触发行动。通常,我使用 combineLatest 作为我的 goto observable composer;然而,如果两个 observables 会更新同一个 action,就会有一个短暂的更新,其中一个 observables 具有来自新状态的值,而另一个具有来自先前状态的值。
最初,我考虑使用 zip observable 创建器来代替;然而,虽然这解决了两个 observable 一起更新时的问题,但它并不能解决一个 observable 在没有另一个 observable 的情况下更新的问题——这在 NGRX 架构中是完全可能的。
然后我考虑了 auditTime(0) 运算符,它确实解决了删除瞬态更新的问题,但有新问题 1) 它会导致 observables 在稍后的事件循环中发出,这会破坏应用程序内部的一些假设(可解决,但很烦人) 2)它使各种可观察对象尽快发射,而我希望所有可观察对象在同一个存储脉冲上一起发射。从图形上看,这意味着应用程序的不同部分的渲染是交错的,而不是在同一帧上一起绘制(请注意,我们的应用程序数据量很大,并且经常需要在存储脉冲上丢帧)
最后,我编写了一个自定义操作符来组合来自同一来源的 observables
export type ObservableTuple<TupleT extends any[]> = {
[K in keyof TupleT]: Observable<TupleT[K]>;
};
export function selectFrom<SourceT, TupleT extends any[]>(...inputs: ObservableTuple<TupleT>): OperatorFunction<SourceT, TupleT> {
return (source$: Observable<SourceT>) => source$.pipe(
withLatestFrom(combineLatest<TupleT>(inputs)),
map(([, values]) => values),
);
}
这里总结一下TypeScript中的问题(使用NGRX、RxJS、Angular的sn-ps)
interface IState {
foo: string;
bar: string;
}
@Injectable()
class SomeService {
constructor(store$: Store<IState>) {
}
readonly foo$ = this.store$.pipe(select(state => state.foo));
readonly bar$ = this.store$.pipe(select(state => state.bar));
readonly composed$ = this.store$.pipe(
selectFrom(
this.foo$,
this.bar$,
),
map(([foo, bar]) => `${foo} - ${bar}`),
);
}
const UPDATE_FOO = {
type: 'update foo',
foo: 'some updated value for foo'
};
const UPDATE_BAR = {
type: 'update bar',
bar: 'some updated value for bar',
};
const UPDATE_BOTH = {
type: 'update both',
both: 'some updated value for both foo and bar',
};
即使 selectFrom 调用相互嵌套,也可以正常工作,例如
readonly composed2$ = this.store$.pipe(
selectFrom(
this.composed$,
this.foo$
)
)
只要在composed2$之前定义commodated$,一切都会顺利;但是,我没有考虑的一个情况是在组合 $ 和组合 2 $ 之间使用 switchMap 之类的运算符时。在这种情况下,由于 compsed2$ 被 switchMap 销毁并重新创建,commodated2$ 可能在composed$ 之前触发,这会导致一切不同步
【问题讨论】:
标签: javascript rxjs ngrx