初心者向けのjQuery入門講座|デザイナー向けのJavaScriptライブラリ

このエントリーをはてなブックマークに追加
索引
Core:コアとなる仕組み
Selectors:セレクタ
Attributes:属性
Traversing:対象の変更
Manipulation:操作
CSS:スタイルシート
Events:イベント
Effects:演出効果
Ajax:xml等との連携
Utilities:ユーティリティ
Data:データ
Miscellaneous:諸々
Deferred:処理管理
Callbacks:コールバック
Internals:内部処理

deferred.then( )コールバックを一括設定/状態の変更

構文

コールバックを一括設定/状態の変更返値:promiseオブジェクト
deferred.then( done )ver1.8〜
deferred.then( done, fail )ver1.5〜
deferred.then( done, fail, progress )ver1.7〜
※done, fail, progressはそれぞれfunctionで設定します。
※function内から新たなdeferredを返すことで状態を変更できます。

機能

deferred.thenメソッドはdefferdオブジェクトの状態によって実行される処理(done, fail, progress)をまとめて設定します。v1.8からは引数にdoneだけ設定しても機能するようになりました。

deferred.thenメソッドのポイントとしては、途中でdeferred(promise)オブジェクトの状態を変更することができる点です(例えば異常終了の状態から正常終了の状態に復帰させることができます)。状態を変更するには、引数に設定したfunction内で新たなdeferred(promise)オブジェクトを作成してreturnで返します。

このページ作成にあたり、以下のサイトが非常に参考になったのでメモしておきます。
→参考:Yahooデベロッパーネットワーク様「爆速でわかるjQuery.Deferred超入門

解説

doneとfailのコールバックを設定

サンプル(then/01.html)を開いてbody内にbutton要素とdiv要素があることを確認してください。jQueryでは、まず以下の部分を確認してください。getメソッドで外部データ「simple.txt」を読込、メソッドチェーンでthenメソッドを連結しました。

thenメソッドではdoneFuncとfailFuncを設定しています。thenメソッドでは引数の順番が決まっている(doneは第1引数、failは第2引数)ので気を付けましょう。

$("button").click(function(){
	$.get("../data/simple.txt").then(doneFunc,failFunc);
});

続いてthenメソッドで設定しているdoneFuncとfailFuncを確認してください。doneFuncでは読み込んだデータをdiv内に表示し、failFuncではアラートで「FAIL!」と表示するようにしています。

function doneFunc(myData){
	$("div").html(myData);
}
function failFunc(myData){
	alert("FAIL!");
}

読み込むデータ「simple.txt」は存在しているので読込に失敗することはありません。実際にbuttonをクリックすると、thenメソッドで設定したdoneFuncの内容が実行されてdiv要素内に読み込んだデータが表示されます。

このサンプルでは分かりやすいようにfunctionを作成してからthenメソッドに設定しましたが、無名関数を利用して直接functionを設定することもできます。サンプル(then/01b.html)を開いて、以下の様にthenメソッドに2つのfunctionが直接設定されていることを確認してください。

$.get("../data/simple.txt").then(
	function (myData){
		$("div").html(myData);
	},
	function (){
		alert("FAIL!");
	}
);

functionを直接設定する場合はカンマを忘れがちです(上記4行目の最後)。忘れないように気を付けましょう。

読込に失敗した場合も確認しておきます。サンプル(then/02.html)を開いて、ほとんどthen/01b.htmlと同じ事を確認してください。ことなるのは読み込むデータが以下の様に「no.txt」に変更されている点だけです。

$.get("../data/no.txt").then(

no.txtは存在しないため読込に失敗します。その結果、2番目に設定されたfunctionの処理が実行され、アラートで「FAIL!」と表示されます。

途中で結果を変更できる

前項で紹介した処理はdoneメソッドfailメソッドをメソッドチェーンで連結して、もっと分かりやすく記述することができます。→サンプル(then/03.html

$.get("../data/simple.txt").done(function (myData){
	$("div").html(myData);
}).fail(function(){
	alert("FAIL!");
});

なのに何故thenメソッドが存在しているかというと、thenメソッドは途中でdeferredオブジェクトの結果(正常終了/異常終了)を変更する事ができるのです。

比較のため、まずはthenメソッドではなく、doneメソッドを利用した前述のサンプルthen/03.htmlを再確認します。このサンプルではsimple.txtがきちんと読み込めるため、doneメソッドで設定された2行目の処理が実行されます。そしてfailメソッドで設定された4行目の処理は実行されません

続いてdoneメソッドをthenメソッドで置き換えたサンプル(then/04.html)を確認してください。functionは1つしか設定していません(v1.8で追加されたdoneのみの構文です)。

変更されているのは、1行目のdoneがthenになっているだけです。あとthenメソッドにメソッドチェーンでfailメソッドが連結されていることも忘れないでください。

$.get("../data/simple.txt").then(function (myData){
	$("div").html(myData);
}).fail(function(){
	alert("FAIL!");
});

buttonをクリックすると、simple.txtがきちんと読み込めるためthenメソッドで設定した処理が実行され、failメソッドで設定した処理は実行されません。then/03.htmlと同じ結果になります。

ではthenメソッドの特徴である、途中で結果を変更するサンプルを確認します。サンプル(then/05.html)を開いて、jQueryに1行処理が追加されているのを確認してください。以下の3行目です。

$.get("../data/simple.txt").then(function (myData){
	$("div").html(myData);
	return $.Deferred().reject().promise();
}).fail(function(){
	alert("FAIL!");
});

3行目では、まずdeferredメソッドで新たにdeferredオブジェクトを作成し、それにrejectメソッドを実行することで、異常終了の状態にします。最後にdeferred.promiseメソッドを利用してpromiseオブジェクトに変換し、returnで返すようにしています。

この処理によってdeferredオブジェクトの状態が変化します。正確には新たに作成したdeferredオブジェクトに上書きされます。新たに作成したdeferredオブジェクトは異常終了にしたため、次のfailメソッドの処理が実行されることになります。

実際にbuttonをクリックして、アラートで「FAIL!」と表示されることを確認してください。またdiv要素には読み込んだデータも表示されているため、thenメソッドで設定したfunctionも実行されているのが確認できます。

最後にdoneメソッドでは、このテクニックが利用できないことを確認しておきます。
サンプル(then/05b.html)を開いて、以下の様にthenメソッドがdoneメソッドに変更されているのを確認してください。それ以外はthen/05.htmlから変更ありません。

$.get("../data/simple.txt").done(function (myData){
	$("div").html(myData);
	return $.Deferred().reject().promise();
}).fail(function(){
	alert("FAIL!");
});

buttonをクリックすると、読み込んだデータはdiv要素に表示されますが、アラートで「FAIL!」とは表示されないため、deferredオブジェクトの状態が変化しなかったことを確認できます。ここでは分かりやすくするためシンプルなサンプルで説明しましたが、メモでは少し実用的なサンプルを紹介しています。

メモ

実用的なサンプル

途中でdeferredオブジェクトの状態を変更できる特徴を活かせば、読込に失敗した場合、予備のデータを読み込むような仕組みを作成する事ができます。

サンプル(then/test01.html)を開いてbody内の構成は、これまでのサンプルと同じ事を確認してください。

jQueryでは、まず以下の部分を確認してください。分かりやすくするため、サンプルthen/01.htmlと同じようにdone用のfunction「doneFunc」とfail用のfunction「failFunc」を作成しました。

ポイントはfailFunc内の処理(5行目)です。外部データ「simple.txt」を読み込むようにしています。getメソッドjqXHRオブジェクト(promiseオブジェクトを内包している)を返すため、これをreturnで返すことによって、deferredオブジェクトの状態を変更する事ができるのです

function doneFunc(myData){
	$("div").html(myData);
}
function failFunc(){
	return $.get("../data/simple.txt");
}

続いて以下の処理を確認してください。buttonをクリックしたら、外部データ「no.txt」を読み込みます。しかしデータが存在しないため異常終了となり、thenメソッドで設定したfailFuncが実行されます。

$("button").click(function(){
	$.get("../data/no.txt").then(doneFunc,failFunc).done(doneFunc);
});

ですがfailFuncでは外部データ「simple.txt」を読み込むようにして、その結果を返すようにしていました。

「simple.txt」は存在し読み込むことができるので、これによって結果が正常終了に書き換えられ、続くdoneメソッドで設定されたdoneFuncが実行されます。結果としてbuttonをクリックするとsimple.txtの内容がdiv要素に表示されます。こうして予備のデータが利用できるわけです。

thenメソッドのdoneの処理を省略したい

サンプルthen/test01.htmlでは最初のデータが読み込めた場合、doneFuncの処理が2回実行されてしまいます。これは正常終了の状態がメソッドチェーンで伝わり、thenメソッドのdoneFuncとdoneメソッドのdoneFuncが実行されるためです。

本当に2回実行されるか確認できるサンプルを用意しました。サンプル(then/test01b.html)を開いてjQueryを確認して下さい。まずdoneFuncでは以下の様にアラートが追加されています。

function doneFunc(myData){
	alert("doneFunc");
	$("div").html(myData);
}

そして以下の様に、読み込む外部データは「simple2.txt」に変更してあります。このデータは存在するため、読込に失敗することはありません。

$("button").click(function(){
	$.get("../data/simple2.txt").then(doneFunc,failFunc).done(doneFunc);
});

buttonをクリックするとアラートが2回表示されることから、doneFuncが2回実行されることが確認できます。doneFuncは繰り返し実行しても問題ありませんが、2回実行する必要もありません。ですので1回しか実行しないように変更します。

とはいえthenメソッドの「構文」にはdoneを省略するような構文はありません。ですがdoneの部分にfalseを設定することで対応することができました。サンプル(then/test02.html)を開いてthenメソッドの第1引数が、以下の様にfalseに変更されているのを確認してください。

$("button").click(function(){
	$.get("../data/simple2.txt").then(false,failFunc).done(doneFunc);
});

これでbuttonをクリックしてもアラートは1回しか表示されません。ちなみに、この手法はanimateメソッドの「引数の省略について」と同じものです。

念のため読込に失敗するサンプルも確認しておきます。サンプル(then/test02b.html)では、以下の様に読み込む外部データが「no.txt」に変更されています。

$("button").click(function(){
	$.get("../data/no.txt").then(false,failFunc).done(doneFunc);
});

しかしfailFunc内の処理によって、予備のデータ「simple.txt」を読込み、これに成功するためdoneFuncが実行されます。これで予備データを読み込む仕組みは完成です。

これまでのサンプルは分かりやすいようにfunction(doneFunc/failFunc)を作成してからthenメソッドやdoneメソッドに設定しましたが、最後に無名関数を直接設定したサンプルを紹介しておきます。
→サンプル(then/test03.html

$.get("../data/simple2.txt").then(false, function(){
	return $.get("../data/simple.txt")
}).done(function(myData){
	$("div").html(myData);
});

falseの代わりにfunctionを設定すると...

前述のサンプルを作成している時に見つけた仕様をメモ。thenメソッドの引数にfalseを設定した場合、読み込んだデータは次のdoneメソッドのfunctionに渡されました(以下3行目)。

$.get("../data/simple2.txt").then(false, function(){
	return $.get("../data/simple.txt")
}).done(function(myData){
	$("div").html(myData);
});

しかしfalseの代わりにfunctionを設定すると、そのfunctionが読み込んだデータを受け取り、後のdoneメソッドのfunctionにはデータは渡りません。つまりデータを受け取れるのは最初のfunctionだけです(よく考えるとfalseを設定した時に、読み込んだデータを次のfunctionに渡してくれるのはとても親切な仕様ですね)。

サンプル(then/test04.html)を開いて、ほとんどjthen/test03.htmlと同じ事を確認してください。ポイントは以下の1行目で、falseではなくカラのfunctionが設定されている点です。またdoneメソッドのfunctionでは受け取ったデータをアラートで表示するようにしました。

$.get("../data/simple2.txt").then(function(){}, function(){
	return $.get("../data/simple.txt")
}).done(function(myData){
	alert(myData);
	$("div").html(myData);
});

buttonをクリックするとアラートが表示されますが、内容は「undefined」となり読み込んだデータが渡されていないのが分かります。thenメソッドに設定したカラのfunctionは引数の設定をしていませんが、それでも読み込んだデータはこのfunctionに渡されるのです。

もしデータを受け取らずに次のfunctionに渡したいのであれば、functionではなくfalseを設定しなければなりません。しかし過去にthenメソッドの代わりに利用されていたpipeメソッド(現在は非推奨)のサンプルを確認して、promiseオブジェクト以外のデータを返せるのではないか?と試してみました。

サンプル(then/test04b.html)を開いて、以下の様に受け取った引数をそのままreturnするようにしているのを確認してください。

$.get("../data/simple2.txt").then(function(test){ return test}, function(){
	return $.get("../data/simple.txt")
}).done(function(myData){
	alert(myData);
	$("div").html(myData);
});

buttonをクリックすると、読み込んだ内容がdoneメソッドに設定したfunctionに渡せることが確認できます。thenメソッドはpipeメソッドの後継なので、同じ機能を持っていないといけないからなのでしょう。