2016-11-16 3 views
0

У меня есть кусок потока, который в императивном языке может выглядеть следующим образом:Идиоматической если-иначе цепи с гм/rxjs

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() не работает.

Теперь мне нужно реализовать это с помощью rxjs 5 с условиями, а также с операциями, связанными с Observables.

Я могу легко получить эквивалент аддонов обратного вызова, создавая Observables и подписываясь повсюду, но это плохо по многим очевидным причинам.

Что такое хороший, идиоматический способ сделать это?

+0

является условием взаимоисключающим (то есть это, если ... else if .... else if?) – Meir

+0

@Meir См. обновление. –

+0

Что такое 'somethingX()' и 'loadDataFromX()'? Если они не возвращают Observables, вы можете использовать только 'map()' или 'concatMap()' в зависимости от того, что вы хотите сделать. – martin

ответ

0

Преобразование обещаний и использование асинхр/ожидает приходит на ум в качестве возможным решения, но с использованием чистого 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);