Sencha Touchで携帯用タイマーを作る

ちょっとSencha Touchで遊んでて、タイマーの操作ってどう書くのがいいのかなーと思って試してみました。
具体的にいうと、Sencha TouchのAPIにExt.util.DelayedTaskというクラスがあって、setTimeoutとどう違うのかな、と。


次のようにsenchaコマンドで生成したアプリケーションをベースにすることを前提にしています。

sencha app create -n Watch -p /hoge/watch


画面はこんな感じで用意します。
https://gist.github.com/3883758#file_app_view_main.js


んで、コントローラなんですけど、setTimeoutを使ったものがこれ。
https://gist.github.com/3883758#file_app_controller_watch_controller1.js


DelayedTaskを使ったものがこれ。
https://gist.github.com/3883758#file_app_controller_watch_controller2.js


setTimeoutを使うときには、呼び出された関数内でのthisはコントローラオブジェクトをあらわさないので、改めてコントローラオブジェクトを渡してやる必要があります。そんで、それを_thisとか引数として受け取って次のように書きます。

    count: function(_this){
        if(!_this.getRunning()) return;
        var c = _this.getCounter();
        var min = c / 60 | 0;//整数化
        var sec = c % 60;
        _this.getTimeLabel().setHtml(min + ":" + sec);
        _this.setCounter(c + 1);
        
        setTimeout(_this.count, 1000, _this);
    }

でも、なんか他と統一感なくてイヤな感じ。


DelayedTaskだと、スコープとしてthisになる値を指定できるので、次のように書けます。

    count: function(){
        if(!this.getRunning()) return;
        var c = this.getCounter();
        var min = c / 60 | 0;//整数化
        if(min < 10) min = "0" + min;
        var sec = c % 60;
        if(sec < 10) sec = "0" + sec;
        this.getTimeLabel().setHtml(min + ":" + sec);
        this.setCounter(c + 1);

        var task = Ext.create('Ext.util.DelayedTask', this.count, this);
        task.delay(1000);
    }

DelayedTaskまわりがゴテゴテするけど、thisがまわりと統一できていい感じ。
本来DelayedTaskが便利なのは、キー入力が終わったら処理をするような場合など、連続するイベントが途切れたときに処理をするといった場合です。でも、コードがSencha APIとして統一できるというメリットもあるようです。


できあがったのがこれです。
https://dl.dropbox.com/u/16392316/timer/index.html
ChromeSafariなど、WebKit系のブラウザで見てください。JavaFXのブラウザでも動きます。


ところで、Sencha Touch、このくらいのアプリなら普通にJavaScriptで書いてもいいし、画面をきれいにするにしても、jQuery Mobileのほうが楽な気がします。
Sencha Touchのメリットは、アプリケーションを記述する場所がちゃんと決められていてソース構造が統一できるということと、強力なデータAPIなので、ちょっと大きめのアプリでデータやりとりが多いものに向くのかなーと、改めて思いました。