有条件扩展的可观察链

时间:2019-08-28 14:05:13

标签: angular typescript rxjs

问题:

我有多个条件要检查。其中一些导致相同的可观察性。

流程如下:

  1. 我检查表单是否保存在本地
  2. 如果是,则显示用户文本1
  3. 如果不是,那么我检查服务器是否在DB中具有此表单
  4. 如果服务器有它,那么我将显示文本2
  5. 如果没有,我将显示文本1

是否有一种方法可以避免导致相同结果但被粘贴的多个条件?

现在看起来像这样

iif(
  () => this.savedLocally,
  this.showText1(),
  this.checkOnServer().pipe(
    switchMap(onServer => iif(
      () => onServer,
      this.showText2(),
      this.showText1()
    ))
  )
)

如果还有一个条件,那么在某处重复this.showText1()就会有一个条件。

我正在寻找的是重新设计这种逻辑,以减少重复。

诀窍在于,我需要执行三项检查(仅当前一项具有预期结果时才执行下一项检查),并且所有这些检查都是异步的。

如果很简单if,我会使用if (cond1 && cond2 && cond3),但是这里并不是那么简单。我对检查有严格的要求,每项检查都取决于先前的结果。

2 个答案:

答案 0 :(得分:0)

您是否绝对需要使用观测值?看起来您也许可以使用简单的异步函数更简洁地编写此代码

async () => {
    if(this.savedLocally) return this.showText1();

    const isOnServer = await this.checkOnServer();
    if(isOnserver) return this.showText2();

    const isAnotherCondition = await this.checkAnotherCondition();
    if(isAnotherCondition ) return this.showText3();

    return this.showText1();
}

答案 1 :(得分:0)

您要描述的是一组可观察对象,其中每个可观察对象都确定是否应使用下一个可观察对象。

如果可观察变量的值不满足条件,则使用下一个可观察变量的值,直到达到收集结束为止,但是如果可观察变量确实满足条件,则不需要其余的任何一个可观察的。

可观察对象完成时,您需要积累条件。

您想要一些可扩展的东西。允许您异步解决一长串条件,但在不需要其他逻辑时停止。

您可以结合使用high-order observablereducers和状态对象。

高阶可观察物是发出可观察物的可观察物。例如;

const higherOrder$ = of(of(true));

让我们使用状态对象来保持 satisfy 条件和值的累积。

interface State {
   // continue when value is false
   satisfy: boolean;
   // accumulation of data
   values: {[key:string]: any};
}

让我们从默认状态值开始。

const DEFAULT_STATE = {
   satisfy: false,
   values: {
      savedLocally: false,
      onServer: false
   }
};

让我们定义将产生将累积的值的可观察物。

  • 每个可观察到的都将发出satisfyvalues
  • 只要satisfy false ,就会使用下一个可观察值。
  • 每个values将累积到最终结果中。
const savedLocally$ = this.http.get(...).pipe(map(resp => ({
    satisfy: Boolean(resp), values: {savedLocally: resp}
})));

const checkOnServer$ = this.http.get(...).pipe(map(resp => ({
    satisfy: Boolean(resp), values: {onServer: resp}
})));

我们可以创建一个高阶可观察值,切换到每个可观察值,累加结果并停止在第一个满足的值上。

在这里,我使用scan()运算符来累加每个发射值上的值。

of(savedLocally$, checkOnServer$).pipe(
   switchMap(ob$ => ob$),
   scan((acc, next) => ({
      satisfy: next.satisfy,
      values: {...acc.values, ...next.values}
   }), DEFAULT_STATE),
   filter(state => state.satisfy),
   first(),
   map(state => state.values)
).subscribe(values => console.log(values));

现在,我不知道这是否比您现在拥有的更简单,但它确实可以扩展以支持一长串可观察量。

在此示例中,switchMap()无权访问上一个状态值。可以做到,但是更复杂,我将需要时间考虑如何去做。