Rx (ReactiveExtension)の事始めとして、RxJSを使ってFizzBuzzしてみる。
準備
<script src="https://cdnjs.cloudflare.com/ajax/libs/rxjs/3.1.2/rx.all.compat.js"></script>
|
ケース1:range, mapを使う
1~100の数値を流すストリームを作成し、それをmap
で変換してみる。
var countStream = Rx.Observable.range(1, 100); var convertedStream = countStream.map(function(x) { if ((x % 15) == 0) return 'FizzBuzz'; if ((x % 3) == 0) return 'Fizz'; if ((x % 5) == 0) return 'Buzz'; return x; }); var output = convertedStream.subscribe(function(x) { $('<span>' + x + '</span><br />').appendTo($('#console')); });
|
ケース2:filterを使う
ケース1では1つのストリームでFizzやBuzzへの変換を行っていたが、Fizzのケースだけ流すストリーム、Buzzのケースだけ流すストリームという具合に分岐させ、それらを合流させて1つのストリームに戻してみる。
var isFizzBuzz = function(x) { return (x % 15) == 0; }; var isFizz = function(x) { return (x % 3) == 0 && !isFizzBuzz(x); }; var isBuzz = function(x) { return (x % 5) == 0 && !isFizzBuzz(x); };
var countStream = Rx.Observable.range(1, 100); var fizzStream = countStream.filter(isFizz).map(function(_) { return 'Fizz'; }); var buzzStream = countStream.filter(isBuzz).map(function(_) { return 'Buzz'; }); var fizzBuzzStream = countStream.filter(isFizzBuzz).map(function(_) { return 'FizzBuzz'; }); var otherStream = countStream.filter(function(x) { return !isFizz(x) && !isBuzz(x) && !isFizzBuzz(x); }).map(function(x) { return x; });
var mergedStream = Rx.Observable.merge(fizzStream, buzzStream, fizzBuzzStream, otherStream); var output = mergedStream.subscribe(function(x) { $('<span>' + x + '</span><br />').appendTo($('#console')); });
|
ケース3:Subjectを使う
以前のケースのように、先に1~100を出力するストリームを作っておいて、というのが気に食わない。
後から流すものを指定したい。
そういう場合にSubjectが使える。
var isFizzBuzz = function(x) { return (x % 15) == 0; }; var isFizz = function(x) { return (x % 3) == 0 && !isFizzBuzz(x); }; var isBuzz = function(x) { return (x % 5) == 0 && !isFizzBuzz(x); };
var subject = new Rx.Subject(); var fizzStream = subject.filter(isFizz).map(function(_) { return 'Fizz'; }); var buzzStream = subject.filter(isBuzz).map(function(_) { return 'Buzz'; }); var fizzBuzzStream = subject.filter(isFizzBuzz).map(function(_) { return 'FizzBuzz'; }); var otherStream = subject.filter(function(x) { return !isFizz(x) && !isBuzz(x) && !isFizzBuzz(x); }).map(function(x) { return x; });
var mergedStream = Rx.Observable.merge(fizzStream, buzzStream, fizzBuzzStream, otherStream); var output = mergedStream.subscribe(function(x) { $('<span>' + x + '</span><br />').appendTo($('#console')); });
Rx.Observable.range(1, 100).subscribe(subject);
|
- 実行: https://jsfiddle.net/n6kpvpdp/
- SubjectはObservable sequenceでありObserverである とのこと
Subject
を作ってそのストリームを filter
, map
するようにしておいて、 subject
に対して流したいものを subscribe
してやる
参考