2006年02月21日

[JavaScript]動的ロード(遅延ロード)2


[][]
Ajax 流行ってるけどさ、
非同期通信の部分とかすっげー効果でるからそこが取り上げられてばっかだけど
実際は JavaScript のごく一部の機能な訳だ。

つー訳で、最近は Ajax ってよりも JavaScript や、プロトタイプベースの
基礎を学びながら遊んでたわけだが、プロトタイプベースっつーのは
クラスベースのOOPとアプローチが全然違うから戸惑ったな。
まず、静的クラスの定義が無いってのがありえんかった。
この辺の話は今度にしよっと。

んでまぁ、プロトタイプベースの JavaScript を
ちょっぴり クラスベース的にかける prototype.js はとっつきやすかった。
Java やってる人は、このコード読むと良いぞ。
中身は洗練されてると思うなぁ。
とりあえず、今の俺の知識じゃケチつけるとこが見つからんくて
ほぉ〜 っと思うような纏まり方してる。

前置きが長くなったが、前回話した動的ロードがサポートされてないのがありえないって続きな。
なんか理由あるんか?だれかちょっと教えてください。
JavaScript でゴリゴリ UI とか Logic 書こうと思ったら
絶対ライブラリ作りたくなると思うんだが
最初にHTMLに埋め込んどけってのは無理だろ!

んで、試したのが次の方法。

@ document.write で script タグ書き出す。
これ、ライブラリ読むためにやるもんじゃねーな。
実行後に書き出されても、スクリプトはそのまま次に進むから、
ここで書き出したライブラリ使ってなんかしようと思ってもうまくいかない事がある。
俺もずっと気付かなかったんだが、IE でずっとテストしてた時は読めてたのに
FireFox でやるとエラーになって気付いたって話。

A document.createElement で document.body に appendChild。
そもそもビックリしたのが
body タグ読み込まれる前に document.body が undefined
な事だなw
document.getElementsId とか、読み込まれてないタグも勿論エラーになる。
結局これで書き出しても、@と同じくすぐに中身使えるわけじゃねーんだけど
最速さん曰く、画面描画が止まらないらしい。
@の方法だと、重いサーバの js 持ってこようとすると、描画が止まるんだってさ。


後は XMLHTTP でもってくる方法も試したけど、同一ドメインしかダメだし
クロスドメインするのに手間かかりそうだし、何故か eval してもうまくいかないからやめた。
同期モードにするのは一番簡単なんだけどな。

body タグがエラーになるのと同じくらいビックリしたのが
sleep がない!
って事だな。
なんでなの? sleep いるくね?誰か知ってる人教えてください。

sleep 無いとなにが困るかっつーと、appendChild したあと ループして読み込み待ちしたいんだが
無限ループしたら、CPU食いつぶしちゃうだろ。
でもそこはまたもや最速さんが、wait 関数なるものを作って処理してた。
function wait(a,func){
var check = 0;
try{
eval("check = " + a);
}catch(e){
}
if(check){
func()
}else{
var f = function(){wait(a,func)};
setTimeout(f,100);
}
}

コードの説明はめんどくさいからしないが、
回帰処理じゃなくて setTimeout で sleep っぽい事してる。
引数の a が読み込んだ js にあるオブジェクトをあらわす文字列で、
func が読み込めたときに callback したい関数オブジェクト。

例えばこれの使い方は
wait('Draggable', function() {
new Draggable('id');
// do something...
}
alert('hogehoge!');


みたいな感じにする。
んで、sleep っぽいっていったのは // do something.. は読み込み完了後に実行されるんだが、
setTimeout ってのはスレッドが止まるわけじゃなくて、指定時間後に再呼出し(再評価)するだけだから
その下のコードは走りつづけるんだな。
だから 「hogehoge!」 ってアラートは、ロードされる前に出るって事。

じゃぁ、import みたいに全ての処理する前に読み込みたいライブラリがいっぱいある場合
var s = document.createElement('script');
s.src = 'http://xxxx/prototype.js'; s.type = 'text/javascript';
document.body.appendChild(s);
wait('Prototype', function() {
var s = document.createElement('script');
s.src = 'http://xxxx/hoge1.js'; s.type = 'text/javascript';
document.body.appendChild(s);
wait('Hoge1', function() {
var s = document.createElement('script');
s.src = 'http://xxxx/hoge2.js'; s.type = 'text/javascript';
document.body.appendChild(s);
wait('Hoge2', function() {
// do something...
}
}
}

とまぁ、誰もこんなあほなコード書かないわな。
眠くなってきたから、次に纏める。



* 関連記事
[JavaScript]動的ロード(遅延ロード)1
[JavaScript]動的ロード(遅延ロード)3


posted by suVene at 23:50