jQueryのAJAX実装をすると、通常、通信が戻ってくるのを待たずに次の処理に進んで、通信の結果はコールバックで処理するよね。
function getResponse(url, parameters, target){
jQuery.post(url, parameters, function(response){
for(i in response){
$(target).html(response[i]);
}
});
}
みたいな感じね。
でも、この処理をまたどこからか呼び出していて、呼び出し元で、この通信が終了している必要がある場合(たとえばappendした結果に対して何か処理したいとか)、普通に
getResponse(‘http://hoge.tld/piyo.php’, {‘request’:’getMessage’}, ‘#targetArea’);
alert($(‘#targetArea’).html());
とかすると、getResponseは要求を作っただけで戻ってきてしまうので、alertの中身は空っぽ、みたいな事になる。
で、これに対応するためにどうするかというと、jQueryのDeferredを使うと良いようだ。
ファンクションの方は
function getResponse(url, parameters, target){
var def = jQuery.Deferred();
jQuery.post(url, parameters, function(response){
for(i in response){
jQuery(target).html(response[i]);
}
def.resolve();
});
return def.promise();
}
みたいな感じで、Deferred.promise()を戻すようにする。
AJAXの戻り値を待つ必要がない既存のコードは、特に何も変えなければそのまま動く。 そして、先のように待機する必要がある場合のコードでは、
jQuery.when(
getResponse(‘http://hoge.tld/piyo.php’, {‘request’:’getMessage’}, ‘#targetArea’)
).done(
function(){
alert($(‘#targetArea’).html());
}
);
みたいな感じにすると、getResponseが返したDeferredがresolveを実行次第doneの中身が呼び出される。
done()は、Deferredにバインドしている形なので、
jQuery.when(
getResponse(‘http://hoge.tld/piyo.php’, {‘request’:’getMessage’}, ‘#targetArea’)
).done(
function(){
alert($(‘#targetArea’).html());
}
);
window.close();
みたいにすると、表示してから閉じると言う動きにはならず、すぐ閉じてしまう。
なお、失敗時のために、resolve doneの組み合わせに対して、reject failがある。。
jQuery.when( asyncFunc() ).done( trueFunc() ).fail( failFunc() );
みたいにすれば、asyncFunc()の返したDeferredでresolve()が実行されればtrueFunc()を、reject()が実行されればfailFunc()が実行されるようになる。
ファンクションが何かの値を戻していた場合、普通に書き換えるとDeferredを戻さなくてはならなくなると言う問題があるが、resolve/rejectに引数として与えると、done/failの引数として引き継がれる。
function getResponse(url, parameters, target){
var def = jQuery.Deferred();
jQuery.post(url, parameters, function(response){
for(i in response){
jQuery(target).html(response[i]);
}
def.resolve(response.length);
});
return def.promise();
}
jQuery.when(
getResponse(‘http://hoge.tld/piyo.php’, {‘request’:’getMessage’}, ‘#targetArea’)
).done(
function(len){
alert(len + ‘:’ + $(‘#targetArea’).html());
}
);
みたいな感じ。
whenはDeferredを複数くっつけるための物なので、1個の実行を待つだけならDeferredを戻すファンクションに対して、 asyncFunc().done(trueFunc()) 的な呼び出しでも良いっぽい。
(10593)