带有rx / rxjs的惯用if-else链

时间:2016-11-16 11:34:21

标签: rxjs rxjs5

我有一个流程,用命令式语言看起来像:

if (something1()) {
  try {
    return loadDataFrom1();
  } catch (err) { }
}

if (something2()) {
  try {
    return loadDataFrom2();
  } catch (err) { }
}

if (something3()) {
  try {
    return loadDataFrom3();
  } catch (err) { }
}

return someSafeDefault();

条件并不相互排斥。可能会发生something1()something2()都为真,在loadDataFrom2()失败时loadDataFrom1()应该出现。{/ p>

现在我需要使用rxjs 5来实现它,条件以及处理Observables的操作。

我可以通过创建Observables并在所有地方订阅来轻松实现回调地狱等效,但由于许多显而易见的原因,它很糟糕。

有什么好的,惯用的方法呢?

1 个答案:

答案 0 :(得分:0)

转换为promises并使用async / await作为一种可能的解决方案,但是使用纯rxjs可以做到这样的事情:

var something1: () => Observable<boolean>;
var something2: () => Observable<boolean>;
var something3: () => Observable<boolean>;

type MyData = { data: string };
var loadDataFrom1: () => Observable<MyData>;
var loadDataFrom2: () => Observable<MyData>;

var first = something1()
    .take(1)
    .filter(something => something ==  true)
    .flatMap(() => loadDataFrom1())
    .catch(e => Observable.of({ message: e }))
    // Take one result, this will be either the sucessful result from lodaData or the err or object { message: e }
    .take(1);

var second = something2()
    .take(1)
    .filter(something => something ==  true)
    .flatMap(() => loadDataFrom2())
    .catch(e => Observable.of({ message: e }))
    // Take one result, this will be either the sucessful result from lodaData or the err or object { message: e }
    .take(1);

var third = something3()
    .take(1)
    .filter(something => something ==  true)
    .flatMap(() => loadDataFrom2())
    .catch(e => Observable.of({ message: e }))
    // Take one result, this will be either the sucessful result from lodaData or the err or object { message: e }
    .take(1);

var safeDefault = Observable.of({data: 'My safe result'});

var result = Observable
    .concat(first, second, third, safeDefault)
    // filter away all exception results
    .filter(data => data.message == null)
    // take only one actuall valid result  
    .take(1);