初めてのRxJSをズンドコキヨシで

  • 4
    Like
  • 0
    Comment
More than 1 year has passed since last update.

※RxJSのドキュメント読んで理解する度に更新してくかも

便乗した。
https://twitter.com/kumiromilk/status/707437861881180160
http://qiita.com/shunsugai@github/items/971a15461de29563bf90

RxJSのドキュメントをみてやっつけでやった。RxJS触るの初めてなので多分よくわかってない。

パターンわかってるからbufferWithCount使えば簡単なのだけど、それよりも途中でSubscribeやめる方法がよくわからんかったのでcompletedみたいな変数を作ってしまい負けた気分。念のため無限ループにはしてない。(一回ミスってjsfiddle固まった)

var zundoko = ["ズン", "ドコ"];
var completed = false;
var zundokoSource = Rx.Observable.generate(
  0,
  function(i) { return i < 10000 && !completed; },
  function(i) { return i + 1;},
  function() { return zundoko[Math.floor(Math.random() * 2 )]}
);

zundokoSource.bufferWithCount(5, 1).subscribe(
  function(kotodama) {
    if(kotodama.join(",") === "ズン,ズン,ズン,ズン,ドコ") {
      console.log("キ・ヨ・シ!!");
      completed = true;
    }
  }
);

リズム版

ズンズンズンズンドコにはリズムがある。ただ単純にズンドコが並べば良いわけではなく、一つ目のズンと二つ目のズンの間は少し長めに、それ以降のズンとドコの間は短めの間がある。

その"間"自体もstreamのデータとして扱い、

ズン 1500ms ズン 750ms ズン 750ms ズン 750ms ドコ

となったときだけ「キ・ヨ・シ」するようにした。1500とか750は別に曲から正確に測ったわけではなく、だいたいである。

実際1500msなり750ms待つこともあり、なかなか「キ・ヨ・シ」を発動できない。

generateWithRelativeTimeを使ったversion

var zundoko = ["ズン", "ドコ"];
var intervals = [1500,750];
var dom = document.getElementById('zundoko');
var completed = false;
var zundokoSource = Rx.Observable.generateWithRelativeTime(
  0,
  function() { return !completed; },
  function() {},
  function() {
    var token = zundoko[Math.floor(Math.random() * 2 )];
    var p = document.createElement("p");
    p.innerHTML = token;
    dom.appendChild(p);
    return token;
  },
  function() {
    return intervals[Math.floor(Math.random() * 2)];
  }
).timeInterval();

var subscription = zundokoSource.bufferWithCount(5, 1).subscribe(
  function(buffer) {
    var zundoko = [];
    var intervals = [];
    buffer.forEach(function(word) {
      zundoko.push(word.value);
      // intervalは関数で指定しか時間ぴったりではなく
      // 数msecずれるので丸め込む
      intervals.push(Math.floor(word.interval / 10));
    })
    console.log(zundoko);
    console.log(intervals.slice(1));
    if(zundoko.join(",") === "ズン,ズン,ズン,ズン,ドコ" &&
      intervals.slice(1).join(",") === "150,75,75,75") {
      completed = true;
    }
  },
  function(error) {
    console.log("error");
  },
  function() {
    var p = document.createElement("p");
    p.innerHTML = "<strong>キ・ヨ・シ!!</srtong>";
    dom.appendChild(p);
  }
);

create使ったversion

var zundoko = ["ズン", "ドコ"];
var intervals = [1500,750];
var zundokoSource = Rx.Observable.create(function(observer) {
  var completed = false;
  function sing(interval) {
    var span = interval / 750;
    var zd = zundoko[Math.floor(Math.random() * 2)];
    var nextInterval = intervals[Math.floor(Math.random() * 2)];
    console.log(Array(span + 1).join("."));
    console.log(zd);
    observer.onNext(interval);
    observer.onNext(zd);
    if(!completed) {
      setTimeout(function(){ sing(nextInterval); }, nextInterval);
    }
  }
  sing(0);
  return function() {
    completed = true;
  };
});

var subscription = zundokoSource.bufferWithCount(9, 1).subscribe(
  function(kotodama) {
    if(kotodama.join(",") === "ズン,1500,ズン,750,ズン,750,ズン,750,ドコ") {
      console.log("キ・ヨ・シ!!");
      subscription.dispose();
    }
  }
);