先日、M3 tech meetup! #2 ~フロントエンドの副作用~に参加してきた。

その中のRxJSで時間を制した話で、ユーザー操作のたびに無駄にAPIがコールされるのを、RxJSのdebounceを使っていい感じにした件なんかが紹介されていた。

この話、個人で作っているサービスのAPI呼び出し回数を減らすのにパクることにした。無料プランで運用しているのでAPIの上限を超えてしまわないか心配だったので。。なんかみみっちい話だけど、趣味のサービスに掛けられるコストは多くない、仕方なし。

RxJSで時間を制した話では、Rx.JSとangular.jsを使っていたのだけれど、自分が作っているサービスはKnoskout.jsを使っているので、Knockout.jsにRx.JSのdebounceに類するものがないか調べたら、ありました。

変更通知を遅延させる|Knockout.js 日本語ドキュメント

rateLimit拡張を使うことで、同じことができるようだ。 通常observableは変更されるとただちに通知を行うのだけれど、rateLimit拡張を使うことで変更の通知を遅らせることができる。

ko.observable().extend({rateLimit:{timeout: 500, method: "notifyAtFixedRate"}})

↑だと、observable最初に変更があった時点 から500ms後に変更が通知される。

このrateLimit拡張は、methodのデフォルトがnotifyAtFixedRateなので、省略して↓の形式の呼び出しもできる。

ko.observable().extend({rateLimit:500})

methodには、もう1種類notifyWhenChangesStopも存在して、こちらはobservable指定した期間変更がなければ 通知が飛ぶ。

rateLimit拡張は、observable以外にもobservable arrayやconputed observableなどの、他のobservableに対応している。すばらしい。

追記

Knockout.jsのrateLimit拡張は、バージョン3.1.0以降の呼び名で、以前はthrottle拡張という名前だったようだ。

ちなみに、lodashにも_.throttleというのがあって、対象の関数の実行を指定期間に1回に制限するものらしい。これはrateLimit拡張のnotifyAtFixedRateの動作に該当する。

そして、_.debounceも存在して、こちらは最後に実行されてから指定時間経過後に関数を実行する。これはrateLimit拡張のnotifyWhenChangesStopの動作に該当する。

で、興味深いのがRx.JSのdebounceは、動作的にはlodashの_.debounceではなくて、_.throttleのほうだということ。lodashとRs.JSの間でねじれが起きてる。


ちなみに、debounceというのは元々ハードウェアだか電子回路の用語だそうです。 debounceという新しい単語を知ることで、連鎖的に知識が広がるいい機会でした。