• Blog.37to.net
    • home
    • blog
    • labs
    • about
    • contact
  • プログラミング・開発 > Kanasan.JS JSDeferred Code Readingが終了しました

    • JavaScript
    • Kanasan.JS
    • イベント
    • 勉強会
    作成:
    2009-06-16T23:13:11+09:00
    更新:
    2009-06-17T00:26:20+09:00
  • 先日に開催された、JSDeferred コードリーディング ( Kanasan.JS : JavaScript Workshop in Kansai)のレポートです。

    ご参加頂いた皆様、ありがとうございました。

    JSDeferred Code Reading

    ソースだけなら数百行なので、時間があまるかも知れないと思っていたのですが、 勘違いも甚だしかったです。

    最後まで読み進める事が出来ませんでした。

    短いライブラリのコードリーディングは初めての企画だったので、色々と反省点がありますが、 以下、気になった所だけ、書いておきます。

    JavaScriptがシングルスレッドであるが故の問題点

    JavaScriptはマルチスレッドをサポートしていないので、時々問題が出てきます。

    例えば以下のようなコード。3秒のスリープを擬似的に作り出しています。

    function foo(){
        var t = new Date;
        while(true){
            if( ( (new Date).getTime() - t.getTime() ) > 3 * 1000 ) break;
        }
        alert('foo');
    }
    function bar(){
        alert('bar');
    }
    

    fooを実行する

    barを実行する

    上記のfooを実行している間に、barの実行が出来ません。

    これがシングルスレッドであるが故の問題点です。

    そこで、この問題を解決するのが、JSDeferredです。

    基本的な仕組み

    JSDeferredの本質は、Deferredオブジェクトを単方向リスト(Singly Linked List)で繋げて、それをsetTimeout(0)で実行している所にあります。 Deferredオブジェクトは非同期で実行する為のfunctionを受け取ります。

    setTimeoutを使う事によって、重い処理を非同期で実行しながら、クリック等のユーザーイベントを挟めるようになります。

    wikiの図が分かりやすいので、最初にそちらを見ると、構造を知るための手助けになります。

    JSDeferred - CodeRepos::Share - Trac

    ここでは、使い方のサンプルを書いてみます。

    <script type="text/javascript" src="jsdeferred.js"></script>
    <script type="text/javascript">
    Deferred.define();
    
    function first(){
        alert("first");
    }
    function second(){
        alert("second");
    }
    function third(){
        alert("third");
    }
    
    function deferredDemo(){
        next(first)
        .next(second)
        .next(third);
    }
    </script>
    <p>
        <a href="javascript:void(0)" onclick="deferredDemo()">実行する</a>
    </p>
    

    実行する

    上記のdeferredDemo()を実行すると、内部では以下のようなイメージで、DeferredオブジェクトのLinked Listが展開されます。

    (new Deferred {
        next : function(){
            setTimeout(function(){
                this.callback.ok();
                this._next.next();
            }, 0);
        },
        callback :{
            ok : first
        },
        _next : new Deferred {
            next : function(){
                setTimeout(function(){
                    this.callback.ok();
                    this._next.next();
                }, 0);
            },
            callback :{
                ok : second
            },
            _next : new Deferred {
               next : function(){
                   setTimeout(function(){
                       this.callback.ok();
                       this._next.next();
                   }, 0);
               },
               callback :{
                   ok : third
               }
           }
       }
    }).next(); //ここで最初のDeferredのnextを実行する。
    

    上記のコードはあくまで、構造のイメージなので、JavaScriptの構文でもなければ、JSDeferredのソース構造とも違う点は注意して頂くとして、 構造の概要をソースで表すと上記のような感じです。

    Deferredオブジェクトは、this._nextに新しいDeferredを持つ事で、単方向のLinked Listを実現しています。

    イメージとしては、コールバック関数をsetTimeout(0)で実行し、 それが終わったら次のDeferredオブジェクトのコールバック関数を、またsetTimeout(0)で実行する。 という繰り返しで、非同期処理を実現しています。

    グローバルのnext()関数と、Deferredオブジェクトのnextメソッドは別物です。 混同しがちだったのですが、コードリーディングの際に知っておくと読みやすくなると思います。

    for〜in構文の面白い書き方

    for〜inで新しい書き方を見つけましたので、抜粋します。

    http://coderepos.org/share/browser/lang/javascript/jsdeferred/trunk/jsdeferred.js
    for (var i in dl) if (dl.hasOwnProperty(i)) (function (d, i) {
        d.next(function (v) {
            values[i] = v;
            if (--num <= 0) {
                    if (dl instanceof Array) {
                            values.length = dl.length;
                            values = Array.prototype.slice.call(values, 0);
                    }
                    ret.call(values);
            }
        }).error(function (e) {
                ret.fail(e);
        });
        num++;
    })(dl[i], i);
    

    ループをeachっぽく書いています。

    外部ライブラリを使わずにforeachのようなループの書き方をしたい時に使えそうです。

    JavaScript 1.6からはforEachが使えますが、クロスブラウザを考慮する時は使えないので、上記のような書き方は面白いと思います。

    変数・メソッド名について

    JSDeferredを使う時は、"parallel"、"wait"、"next"、"call"、"loop"という、とても分かりやすいfunctionだけ覚えればいいので、 使う分にはとても楽です。

    但し、内部的にはこれが複雑に見える要因にもなり、window.next()とDeferred.next()の違い、 Deferred.prototype.nextとDeferred.nextの違い等が、コードを読みにくくする一因にもなっています。

    プロトタイプのオブジェクト指向を学ぶ上では、prototypeの使い方のお手本にはなると思います。

    個人的には他にも、Deferred.callとネイティブメソッドのFunction.callが混同してしまいました。

    上記のような事から、APIとして使う変数名は分かりやすくても、 内部の命名が分かりにくいという意見がちらほら聞かれました。

    wrapの謎

    時間切れで途中までしか読めませんでした。

    今の所の結論としては、Deferredオブジェクトを拡張する為にregisterメソッドというのがあるのですが、 そこでしか使われれていない事から、Prototype.jsのbind()のようなイメージで引数の束縛をしているのだと思います。

    ゆるふわTech Talk

    今回はTechTalkの時間が多すぎて、本編の時間を圧迫してしまった事が反省点の一つでした。 次回以降は気を付けたいと思います。

    37to

    私37toはどこにも告知していなかった、flickwriterというGreasemonkeyを紹介しました。

    Firefoxの拡張、Make Link :: Firefox Add-onsの Flickr版とも言えるGreasemonkeyです。

    Flickrの写真ページから、各写真サイズのリンクを簡単に取得する事が出来ます。

    flickwriter for Greasemonkey

    issmさん

    DQWindowManagerの紹介。

    DQWindowManager - Webをドラゴンクエストっぽく遊ぼう!

    一言で言うと、ドラクエ風のウィンドウメニューを作れる。

    それだけでも、ドラクエが好きな人には十分なのですが、 なんとプレゼンが出来たり、どっかのサイトのブックマークレットを拾って、 自分のメニューに加える事が出来たりします。

    サーバーサイドも含めてのサービスなので、ユーザーだけ集まれば、とても面白い事が出来ると思う。

    たとえば、今同じページを見ている人が、ページ内をうろうろしていたり、 その人にメッセージを送ったり等々。

    最近は開発が止まっているようですが、とても面白いサービスだと思いました。

    Sixeightさん

    Lingrでも使われていたプッシュ配信技術、「Comet」を利用した「Comets」の紹介。

    Sixeight's comets at master - GitHub

    実用的にはまだ達していないとの事でしたが、サーバー側のソースは100行程のようで、 Comet実装のサンプルとしては、非常に良い題材と思いました。

    会場では、運用レベルになるとやはり同時接続数、ポートの枯渇が問題になってくるという話が出ていました。

    okkezさん

    Stack Stock BooksのAPI + jQuery + Rubyを使ったサービスの紹介。

    JavaScriptでインクリメンタル検索のライブラリ(jQueryのプラグインかな?)が動かないという話が出ていたのですが、 その場で参加者からいくつもの解決案が出てきました。

    こういうケースを見てると、とりあえず発表してみるのは重要だと感じました。

    発表を躊躇している方々も、気負いせずに軽いタッチで発表してもらえると、嬉しい限りです。

    懇親会

    「あじと」いう居酒屋にて。

    焼酎と肴 京橋 あじと/ホットペッパー.jp

    たまたま席順が学生とその他で席が分かれてしまい、ジェネレーションギャップを感じていました。

    私自身が端っこに座っていた事もありますが、もう少し全体を盛り上げる為の気遣いが足りなかったかなと、反省しています。

    Lingrの代替

    Lingrに依存していた勉強会は、移行先に四苦八苦されていると思いますが、 Kanasan.JSでは、Web上でSkypeのチャットが出来る、SkWebChatを使ってみました。

    SkWebChat(Webで使えるスカイプチャットサービス)

    IRCやSkypeのグループ(最新版Winクライアントでは、オープンチャットが使えない)、 他にはTwitterやWassrも検討していましたが、以下の点からSkWebChatを選びました。

    • ブラウザだけあれば、Skypeのアカウントが無くても発言できる
    • ログが残る

    誰でも発言出来るという点が良かったです。

    ただ、終わってみると発言がいつもより少ないのが気になりました。

    コードリーディングが難解だからか、チャットのUIがLingr程よくはないからかは分かりませんが、 もう少し様子を見ようと思います。

    本命はGoogle Waveなので、今からサービスインを楽しみにしています。

    会場

    今回は初めての会場でした。

    大阪府私学教育文化会館

    少し会場費が高いのですが、従業員の方の対応がとても良かったです。

    LANも問題なく繋がり、京橋の近くなので交通の便もよく、とても良かった。

    会場費は少し高いのですが(空調機を使うと30%増し。備品は安いほうかと)、LANが必要な会場の候補としては良さそうです。

    入ると湯のみが人数分置いてあり、お茶がサービスで出ました。

    従業員の方の対応が良かったからか、また使いたいなと思いました。

    最後になりますが、ご参加頂いた方々、ありがとうございました。

    今回は特にid:yaottiと、 id:Sixeightの両スタッフの助けが無ければ、 開催出来なかったと思います。とても助かりました、ありがとうございました。

    • Kanasan.JS JSDeferred Code Reading
    • ページ上部へ戻る
    • サイトをリニューアルした時のメモ

    Posted at 37to : commetns(0) : trackbacks(0)

  • 同一カテゴリのエントリ

    • サイトをリニューアルした時のメモ
    • Kanasan.JS JSDeferred Code Readingが終了しました
    • JavaScriptでCSSとイベントを扱う from Kanasan.JS
    • Firebugで作るGreasemonkeyスクリプト〜入門と実践(From Kanasan.JS)
    • 2008年度のEmacsをまとめたメモ
  • 関連エントリ

    • JavaScriptでイベントをエミュレートする(From Kanasan.JS 読書会#8)
    • Kanasan.JS JSDeferred Code Reading
    • JavaScriptでCSSとイベントを扱う from Kanasan.JS
    • Firebugで作るGreasemonkeyスクリプト〜入門と実践(From Kanasan.JS)
    • prototype.jsの内側から覗くJavaScriptの世界(from Kanasan.JS)
  • 関連商品

  • コメント

    コメントはありません
  • トラックバック

    本エントリへのトラックバックURL http://blog.37to.net/mt/mt-tb.cgi/117

    トラックバックはありません
  • About

    about

    Name
    37to (minato)
    Job
    Web Developper
    Community

    Kanasan.JS

    関西を中心に活動するJavaScriptの勉強会

    ...more about

    Twitter Updates

      follow me on Twitter
    • Categories

      • Web・コンピュータ(24)
      • お知らせ(1)
      • コンピュータ・ガジェット(3)
      • プログラミング・開発(39)
      • 雑記(12)
    • Tags

      • (X)HTML
      • CSS
      • del.icio.us
      • Firefox
      • JavaScript
      • Kanasan.JS
      • MovableType
      • PHP
      • Python
      • RSS
      • SBM
      • Web
      • はてな
      • イベント
      • オブジェクト指向
      • テンプレート
      • デザイン
      • フォーム
      • 雑記
      • 勉強会
    • Archives

      • 2012年1月(1)
      • 2009年12月(1)
      • 2009年10月(1)
      • 2009年6月(3)
      • 2009年4月(2)
      • 2009年3月(1)
      • 2009年2月(1)
      • 2009年1月(1)
      • 2008年12月(1)
      • 2008年11月(2)

      ...more archives

    • Feeds

      • blog feedBlog.37to.netBlog.37to.netのフィード
      • 37to's reading new feedlivedoor Readerの新着フィード - k_37to
      • 37to's New Bookmark Feeddel.icio.us - 37to's Bookmark Feeds
    • Sorcial Bookmarks

      • livedoor クリップ - k_37tolivedoor クリップ - k_37to
      • はてなブックマーク - k_37toはてなブックマーク - k_37to
    • Copyright © Since 2006-2012 37to
    • Home | blog | labs | about | contact | feed