RxJS观测值合成的布尔代数帮助器

RxJS观测值合成的布尔代数帮助器,rxjs,boolean-operations,Rxjs,Boolean Operations,如何避免编写疯狂的combinelatetest语句来计算简单的布尔逻辑表达式 这个简单的表达式几乎不适合stackoverflow代码控件,如果你不小心对参数重新排序,你将很难进行调试 this.showPlayButton = combineLatest(this.playPending, this.isReady, this.showOverlay) .pipe( map(([playPending, isReady, showOverlay]) => isReady &a

如何避免编写疯狂的
combinelatetest
语句来计算简单的布尔逻辑表达式

这个简单的表达式几乎不适合stackoverflow代码控件,如果你不小心对参数重新排序,你将很难进行调试

this.showPlayButton = combineLatest(this.playPending, this.isReady, this.showOverlay)
  .pipe(
   map(([playPending, isReady, showOverlay]) => isReady && !playPending && showOverlay),
   distinctUntilChanged();

好吧,我很惊讶我找不到一个现有的库,所以我开始收集一些助手可观察的创建函数

可观察的
助手 这些是“最纯粹”的助手,接收和输出
可见的
。我在每一项中都添加了
distinctUntilChanged()
,这样可以防止多次不必要的排放。这是一个非常惰性的操作符,没有
share
shareReplay(1)
更复杂的后果,但重要的是要知道它已经被应用

export const allTrue = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.every(v => v == true) ), distinctUntilChanged());
export const allFalse = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.every(v => v == false) ), distinctUntilChanged());
export const anyTrue = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.find(v => v == true) != undefined ), distinctUntilChanged());
export const anyFalse = (...observables: Array<ObservableInput<boolean>> ) => combineLatest(observables).pipe(map(values => values.find(v => v == false) != undefined), distinctUntilChanged());

export const not = (observable: Observable<boolean> ) => observable.pipe(map(value => !value), distinctUntilChanged());
还有第三类,如
iff
,相当于SQLServer的station。这些参数的输出为
A
B
(参数类型)。这就像一个非常简单的if语句

export const iff = <A, B>(ifObs: Observable<boolean>, trueValue: A, falseValue: B) => ifObs.pipe(map(value => value ? trueValue : falseValue));
至于最初的问题,它变成了这样:

this.showPlayButton$ = allTrue(this.isReady$, not(this.playPending$), this.showOverlay$)

当我提出新的问题时,我会将其添加到这个列表中。这些都涵盖了我到目前为止遇到的大多数情况。这当然可以制作成一个库,但我现在无法将其正式化,以便能够做到这一点。如果有些东西已经存在,我想比较一下:-)

很好。考虑将用于
map
filter
scan
的rxjsapi与
Array
类似。我倾向于使用
每一个
一些
,而不是
所有
任何
,因为这是
数组
@cartant所使用的,谢谢:)当然这只是一个开始,但我发现这些对于编写更干净的代码来说是非常宝贵的,特别是当我有一系列布尔值准备UI时。你当然可以在很多方面采取这一点,我希望看到有人能够正式化他们,并考虑进一步的选择。我可能会在我自己的版本中留下这些名称(或一些小的更改),因为我的目标之一是使代码尽可能接近英语,并且通常不使用pipe()。对我的用例来说,这种独特的检查也是经过深思熟虑的,但您是否希望在库中使用这种检查仍有争议。
loading$ = not(this.loaded$);
hasSelectedOrder$ = isTruthy(orderId$);  // Note: this wouldn't work for something zero
hasSelectedOrder$ = isDefined(orderId$);  // uses != undefined 

layout$ = iff(deviceType.isDesktop$, 'horizontal', 'vertical');
isMobileOrTablet$: anyTrue(this.isMobile$, this.isTablet);
isTabletOrDesktop$: anyTrue(this.isTablet, this.isDesktop$);

isBusy$ = anyTrue(this.hasBusyTask$, this.busyService.isBusy$);

// very useful for UI (using async pipe)
isAddNewCreditCardSelected$ = isEqual(selectedPaymentMoniker$, 'NEW');
showSavedPayments$ = allTrue(showAvailablePaymentMethods$, hasVault$, not(isAddNewCreditCardSelected$));
showAddCreditCardButton$ = allTrue(showPaymentButtons$, not(showAddCreditCardPanel$), not(showVault$))
showDefaultFooter$ = allTrue(not(this.isWebapp$), this.showDefaultFooter$);
showBusyIndicator$ = allTrue(not(this.pageService.handlesBusyIndicator$), this.busyService.isBusy$) ;
this.showPlayButton$ = allTrue(this.isReady$, not(this.playPending$), this.showOverlay$)