「う〜む、これはちょっと違うな」
前回までのあらすじ:
「ガイド屋 mini」のリリースでJavaScript童貞を卒業したばかりだというのに、いきなり「FlashUI」というムリ目狙いを「情報屋」で成し遂げたナカトジ。その様はイケイケ時代を生きた80'sオヤジにふさわしいものと言えよう。しかし、彼の「企て」の前には、まだまだ超えなければならない壁があるのだった……
FlashUIのドタバタ以来、すっかり参考にさせていただいているkamisetoさんのページなのですが、少々気になるくだりがありました。
BridgeTalkは同期も非同期もいける
BridgeTalkは非同期なのかと勘違いしていたんだけど、
onResultに無名関数でもいいのでonResultに関数を設定すれば、
処理が終わるまで待ってくれるみたい。
BridgeTalkにたどりつくまではそれほど気にとめていなかったのですが、いよいよ自らがそれを実践しようというときになって、ふとプログラマー的なカンから「?」と思ったのです。
イベントドリブン的な考え方から推測すると、onResultは多分、何時も非同期。あくまでイベントループにフックを掛けているに過ぎない。つまり、BridgeTalkに対して「返事があったら教えてね」と伝えただけであって、「ここで待ってるから戻ってきてね」ということ「ではない」……はず。
「だとしたら何か違うっていうのさ?」
それが大違いなんだな。よーし、オジサンが自分で実験してみよう。
まずは単純に「onResult」にイベント処理を書いてみます。うまくいけばInDesignで選択した画像がPhotoshopで開かれるはず……
うまくいきました。しかし、この結果から「onResult」は同期すると思い込んでしまうと痛い目に遭います。おそらく、そのままここに関数を書き連ねてソースコードを見づらくしてしまうか、サジを投げるかのどちらかでしょう。それは次の実験を見れば分かります。
お〜っと、最終行での返り値が「undefined」です。ソースコードを見直しても、最初の実験と比べても、構文チェックしてみてもどこもおかしいと思えるところがないように思えます。しょうがない、うまくいったコードに付け足して書いていくか。それともあきらめようか……
その前にオジサンの言葉をもう一度思い出してください。
BridgeTalkに対して「返事があったら教えてね」と伝えただけ
ここです。そう、彼(コード)は「〜教えてね」と言い残し、さっさと次の場所に行ってしまったのです。つまり、その次の「btObj.send();」を実行し、すぐに(代入後)「alert( rest );」を実行しているのです。よほどこの間の実効速度が遅くなければ「onResult」より先にこちらが実行されるはずです。返り値が「undefined」なのは当然の結果と言えるでしょう。
オブジェクトのやりとりの何かで空っぽなんじゃないの〜?
まだ信じられない向きにはトドメをさしておきましょう。
先ほどの理屈を証明するように、最終行のアラートが先に表示されるはずです(よほど……でなければ)。
かといって、このまま「onResult」にイベント処理を書き連ねるのはスマートではありませんし、特に長い処理になる場合は問題(バグ)の切り分けがしづらくなってしまいます。できればほかの部分で処理したい(書きたい)ものです。ここまで理解できればあえてソースコードを書くまでもありませんが、以下のような感じで処理すればよいでしょう
というわけで「相手のレスポンスを捕まえてから処理することが可能」ですが、それが「同期がとれている」とは思い込まないようにしましょう。いつか間違いなくハマリます。
さて、BredgeTalkの挙動がスッキリしたところでさらに一考。
実際のところ「BridgeTalk送受信部」はプロトタイプで実装するのがスマートなのでしょうが、私はまだ使いこなせておりません。それはいずれ実装するとして、このままでもBridgeTalk送受信部を使い回すアプローチはあります。
最終的には送信部そのものをその時の仕様にあわせて最適化してしまえばよいわけですが、開発中はこのような作りが有用だったりします。