GreaseMonkeyのGM_xmlhttpRequestで同期通信(モドキ)

キーボードが打ちたいので文章作成。


2007/06/05現在、GM_xmlhttpRequestが同期通信できません。(多分)

なので、繰り返しGM_xmlhttpRequestを行う時に、こんなことをやると・・・・

// 関数foo を通信の1単位
var foo = function(){
  GM_xmlhttpRequest({
    method: "GET",
    url: "http://ドコカ",
    header: {
      "User-Agent": "gmonkeyagent",
    },
    onload: function(r){
      alert(ReqCount);
    }
  });
}


// foo後、+1される変数
var ReqCount = 0;


// 関数foo を5回使ってみる。
for(var i=0; i<5; i++){
  foo();
  ReqCount += 1;
}

なんて書くと・・・・
接続先にもよるが大抵の場合「5」と表示されたアラート画面が五回出てくるだけになる。

原因は・・・

非同期通信だから、通信をはじめても処理は待ってくれない。
故に五回の通信が完了するころには、5回ループが終わってる状態なんですね。


解決方法としては二つ考えた。

** 解決方法その1 ** GM_xmlhttpRequestを使わない。

ネガティブな解決方法。自分はやったこと無い。
もともとブラウザが持ってるjavascriptの通信関数を使う。
GMスクリプトの対象となっているサイトがprototype.js等を読み込んでるんだったら、unsafeWindowを使って頑張ればできる。(はず)
参考:http://d.hatena.ne.jp/daftbeats/20070519/1179570856
というか、GMprototype.jsのオブジェクトAjax.requestのインスタンス生成がうまくできないのですよ。

** 解決方法その2 ** GM_xmlhttpRequest再帰

うん。GM_xmlhttpRequestの変数onloadの中でGM_xmlhttpRequestを使うんですよ。
上のコードを書き換えると、

// 関数foo を通信の1単位
// 引数nは繰り返しの回数。
var foo = function(n){
  if(n==0){
    return 0;
  }
  GM_xmlhttpRequest({
    method: "GET",
    url: "http://ドコカ",
    header: {
      "User-Agent": "gmonkeyagent",
    },
    onload: function(r){
      alert(ReqCount);
      ReqCount += 1;


      foo(n-1); // 最後に「引数を-1した自分自身」を呼び出す。
    }
  });
}


// foo後、+1される変数
var ReqCount = 0;


// 関数foo を5回使ってみる。
foo(5);

こう。

** 解決方法その2 ** の問題点

  • みづらい。

通信の一単位とは言えない状態になってます。


以上です。
他にいい方法無いかなぁ。