2016-03-24 5 views
1

そう...は http://underscorejs.org/#compose Returns the composition of a list of functions, where each function consumes the return value of the function that follows. In math terms, composing the functions f(), g(), and h() produces f(g(h())).RxJSの関数f(g(h))を機能的にどのように構成するか?アンダースコアで

とにもアンダーずに減らす使用して同じ効果を得ることができ、「構成」と呼ばれる機能があります:

var mappers = [ 
    function add_100(v) { 
     return v + 100; 
    }, 
    function mul_2(v) { 
     return v * 2; 
    } 
]; 

console.log(
    [1, 2, 3].map(function (n) { 
     // we transform n by passing it to the all mappers 
     // so result will be: mul_2(add_100(n)) 
     return mappers.reduce(function (currentResult, mapper) { 
      return mapper(currentResult); 
     }, n /* initial value for pipeline */) 
    }) 
); // ---> [202, 204, 206] 

// because: 
// (1 + 100) * 2 = 202 
// (2 + 100) * 2 = 204 
// (3 + 100) * 2 = 206 

をしかし、このアプローチは良いです関数add_100またはmul_2が同期していて直ちに値を返すとき。非同期機能が必要なので、私はRxJSを使い始めました。

もちろん、RxJSにはreduceという演算子がありますが、VanillaJSのように同期して動作するようです。

var Rx = require('rx') 
var mappers = Rx.Observable.from([ 
    function add_100(v) { 
     return v + 100; // works in Rx because it's synchronous 
    }, 
    function mul_2(v) { 
     return v * 2; // works in Rx because it's synchronous 
    } 
]); 

Rx.Observable.from([1, 2, 3]).map(function (n) { 
    // we transform n by passing it to the all mappers 
    // so result will be: mul_2(add_100(n)) 
    return mappers.reduce(function (currentResult, mapper) { 
     return mapper(currentResult); 
    }, n /* initial value for pipeline */) 
}).mergeAll().subscribe(console.log) 
// 202 
// 204 
// 206 

関数add_100とmul_2が非同期の場合即値の代わりにObservableを返します。それはもはや動作しません。

だから... ...私は実際にこれを歩くためにいくつかのソリューションを作るが、それは醜いと非常に明確ではありませんになります。私はES6から矢印の表記を使用してい

var Rx = require('rx') 
var mappers = Rx.Observable.from([ 
    function add_100(v) { 
     return Rx.Observable.create(
      o => { 
       // line below concerns me most: 
       v.subscribe(value => o.onNext(value + 100)); 
      } 
     ); 

     return Rx.Observable.from(v + 100); 
    }, 
    function mul_2(v) { 
     return Rx.Observable.create(
      o => { 
       v.subscribe(value => o.onNext(value * 2)) 
      } 
     ); 
    } 
]); 

Rx.Observable.from([1, 2, 3]).map(function (n) { 
    return mappers.reduce(function (currentResult, mapper) { 
     return mapper(currentResult); 
    }, Rx.Observable.from([n]) /* initial value for pipeline */).mergeAll(); 
}).mergeAll().subscribe(console.log) 

ノート。 ES5ではもっと醜いものに見えるでしょう。

Rx.Observable.from([1, 2, 3]) 
.map(Rx.compose(mappers)) // my imaginary Rx.compose util like in Underscore 
.mergeAll() 
.subscribe(console.log) 

あるいは、少なくともいくつかのハックソリューションは、私が把握したことよりよい:

私が本当に望んでいたことは、このようなものです。もちろん、私は自分のユーティリティを作ることができますが、これは問題ではありません。私は多分これらの種類の問題のためのいくつかの素晴らしいRxの方法のソリューションがあるのだろうか? Rxは高水準のライブラリなので、ホイールを再発見せずに、Rx /リアクティブアプローチでもっと経験豊富な人が何を言うのか聞いてみるといいかもしれません。

またはおそらくinb4私は "あなたのソリューションはエレガントで、何も間違っていない"と聞きます。多分。私はこのコードを見ると精神的なオーバーヘッドを感じるだけです。

+1

こちらをご覧くださいhttps://jsbin.com/kavagi/1/edit?js,consoleおそらくそれはあなたのために役立つでしょう – xgrommx

+0

あなたは['composeP'](http://ramdajs.com /0.19.1/docs/#composeP):-) – Bergi

+0

composePは約束 – xgrommx

答えて

1

私は非常に簡単な解決策を考え出しました:

// ... (initializing code the same like above) 

Rx.Observable.from([1, 2, 3]) 
    .flatMap(mappers[0]) 
    .flatMap(mappers[1]) 
    .subscribe(console.log); 

のみ(マッパーの数は不明である)、より柔軟な方法で作られた:それは、この機能的に同等です

var Rx = require('rx'); 
var mappers = [ 
    function add_100(v) { 
     return Rx.Observable.return(v + 100); 
    }, 
    function mul_2(v) { 
     return Rx.Observable.return(v * 2); 
    } 
]; 

mappers.reduce(// magic happens here 
    (o, mapper) => o.flatMap(mapper), // and exactly here. 
    Rx.Observable.from([1, 2, 3]) // initial observable we want to transform 
).subscribe(console.log); 

// 202 
// 204 
// 206 

を。

関連する問題