6. 非同期処理¶
この章では、非同期処理の実装や制御に関連する方法を説明する。
6.1. Deferredによる非同期処理制御¶
6.1.1. 概要¶
利用ライブラリ | サンプル | 参考ページ |
---|---|---|
jQuery | - | Deferred Object | jQuery |
6.1.2. Deferredのメリット¶
サンプル |
---|
1秒毎にメッセージを出力 |
setTimeout(function () {
$('#deferred-area').append('<p>1</p>');
setTimeout(function () {
$('#deferred-area').append('<p>2</p>');
setTimeout(function () {
$('#deferred-area').append('<p>3</p>');
}, 1000);
}, 1000);
}, 1000);
サンプル |
---|
1秒毎にメッセージを出力(Deferred適用) |
// (1)
var outputMessage1 = function () {
// (2)
var dfd = new $.Deferred();
setTimeout(function () {
$('#deferred-area').append('<p>1</p>');
// (3)
dfd.resolve();
}, 1000);
// (4)
return dfd.promise();
};
// (5)
var outputMessage2 = function () {
/* omitted */
};
// (5)
var outputMessage3 = function () {
/* omitted */
};
// (6)
outputMessage1()
.then(outputMessage2)
.then(outputMessage3);
項番 | 説明 |
---|---|
(1)
|
1秒後にメッセージ「1」を出力する関数。
|
(2)
|
deferredオブジェクトを生成する。
|
(3)
|
非同期処理内で最後にdeferredオブジェクトの状態を変更する。
deferredオブジェクトの状態については後述する。
|
(4)
|
promiseオブジェクトを返却する。
|
(5)
|
メッセージ「2」「3」を出力する関数。
outputMessage1とほぼ同一であるため、実装は省略する。
|
(6)
|
outputMessage1を実行し、thenで後続の非同期処理を連結する。
thenについては後述する。
|
Note
thenを実行すると、promiseオブジェクトにコールバックを設定し、新たなpromiseオブジェクトが返却される。thenを繰り返すとpromiseオブジェクトが連鎖し、コールバックが直列的に実行される。
Note
promiseオブジェクトは、deferredオブジェクトから状態を変更するメソッドを削除したサブセットである。状態を変更できる箇所を限定することで、意図せず後続処理が実行されることを抑止する。
6.1.3. Deferredの利用方法¶
6.1.3.1. Deferredによるコールバックの切り替え(then)¶
サンプル |
---|
thenによるコールバックの切り替え |
// (1)
var random = function () {
return Math.floor(Math.random() * 2) === 1 ? true : false;
};
var async = function () {
var dfd = new $.Deferred();
setTimeout(function () {
var result = random();
$('#deferred-area').append('<p>Result is ' + result + '.</p>');
if (result) {
// (2)
dfd.resolve();
} else {
// (2)
dfd.reject();
}
}, 1000);
return dfd.promise();
};
// (3)
var success = function () {
$('#deferred-area').append('<p>success</p>');
};
// (3)
var failure = function () {
$('#deferred-area').append('<p>failure</p>');
};
// (4)
async().then(success, failure);
項番 | 説明 |
---|---|
(1)
|
trueかfalseをランダムに返却する関数。
|
(2)
|
ランダム関数の結果に応じてdeferredオブジェクトの状態を変更する。
|
(3)
|
メッセージを出力する関数。
|
(4)
|
引数にコールバックを渡す。
|
メソッド | 状態 | 実行するコールバック |
---|---|---|
resolve
|
resolved
|
第1引数
|
reject
|
rejected
|
第2引数
|
6.1.3.2. Deferredによるコールバックの切り替え(done・fail)¶
サンプル |
---|
done・failによるコールバックの切り替え |
// (1)
async()
.done(success)
.fail(failure);
項番 | 説明 |
---|---|
(1)
|
引数にコールバックを渡す。
|
メソッド | 状態 | 実行するコールバック |
---|---|---|
resolve
|
resolved
|
doneの引数
|
reject
|
rejected
|
failの引数
|
Note
done・failを実行すると、promiseオブジェクトにコールバックを設定し、同一のpromiseオブジェクトが返却される。done・failを繰り返すと1つのpromiseオブジェクトに複数のコールバックが積み上げられ、ほぼ同時に実行される。thenと挙動が異なる点に注意すること。
Note
then・done・failの他にalwaysがある。alwaysはresolved・rejectedのどちらの状態でも実行される。
6.1.3.3. 非同期処理の並列連結(when)¶
サンプル |
---|
非同期処理の並列連結 |
// (1)
var asyncFuncA = function () {
var dfd = new $.Deferred();
setTimeout(function () {
$('#deferred-area').append('<p>functionA has ended.</p>');
dfd.resolve();
}, 1000);
return dfd.promise();
};
// (2)
var asyncFuncB = function () {
/* omitted */
};
// (2)
var asyncFuncC = function () {
/* omitted */
};
// (3)
var outputMessage = function () {
$('#deferred-area').append('<p>All of the function has ended.</p>');
};
// (4)
$.when(asyncFuncA(), asyncFuncB(), asyncFuncC())
.then(outputMessage);
項番 | 説明 |
---|---|
(1)
|
非同期処理終了後にメッセージを出力する関数。
|
(2)
|
非同期処理終了後にメッセージを出力する関数。
asyncFuncAと同様であるため、実装は省略。
|
(3)
|
全ての処理が完了後にメッセージを出力する関数。
|
(4)
|
非同期処理からpromiseオブジェクトを受け取る。
thenの引数にメッセージ出力処理を設定する。
|
Note
whenに複数の非同期処理を渡すと、pendingの状態を持つpromiseオブジェクトが返却される。 promiseオブジェクトは各非同期処理の状態を管理しており、全ての非同期処理がresolvedになるか、1つでもrejectedになるとthenのコールバックを実行する。
なお、後者の場合は実行中の非同期処理の完了を待ったり、中断することなくコールバックの実行に移る。必要に応じて中断処理などを実装すること。
6.1.4. 応用方法¶
6.1.4.1. Ajaxの再利用¶
サンプル |
---|
Ajaxの再利用 |
var doAjax = function () {
var dfd = new $.Deferred();
// (1)
$.ajax({
url : 'js/deferred-promise-sleep.js',
dataType : 'script'
// (2)
}).then(dfd.resolve);
return dfd.promise();
};
// (3)
var funcA = function () {
$('#deferred-area').append('<p>Do function A.</p>');
};
// (3)
var funcB = function () {
$('#deferred-area').append('<p>Do function B.</p>');
};
// (4)
doAjax().then(funcA);
// (4)
doAjax().then(funcB);
項番 | 説明 |
---|---|
(1)
|
非同期通信を実行する。
|
(2)
|
非同期処理終了後に状態を変更する。
|
(3)
|
メッセージを出力する関数。
|
(4)
|
非同期通信を実行し、thenの引数にメッセージを出力する関数を設定する。
|
Note
サンプルでは、ajaxにthenを実装している。 ajaxは、jQuery XMLHttpRequest(以降、「jqXHR」とする。)を返却する。jqXHRはpromiseオブジェクトのインターフェースを実装しており、サンプルのようにthenやdone・failを実行することが可能である。詳細は jQuery公式ウェブサイトのリファレンスを参照すること。