どうもはじめまして、
JavaSciptにおける非同期処理
非同期処理とは
まずは確認程度に、
- 非同期とは
「あとで」 という意味 - 同期処理はコードの見た目順に実行される/
非同期ではそうならない - JavaScript の非同期処理は絶対に同期処理にすることができない
JavaScriptにおける非同期処理をいくつか例に出すと、
// XMLHttpRequest の例
var req = new XMLHttpRequest();
req.open('GET', 'http://example.com/', true);
req.onreadystatechange = function (e) {
if (req.readyState == 4)
alert('async!')
}
};
req.send(null);
alert('hello');
// setTimeout の例
var sid = setTimeout(function () {
alert('async!');
}, 0);
alert('hello');
// イベントの例
document.body.onclick = function (e) {
alert('async!');
};
alert('hello');
これらは、
コールバック関数を渡す関数は非同期になっていることも多いですが、
例にあるように setTimeout でタイムアウト時間を 0 にしたとしても、
このコールバックをとって関数を非同期実行させるのは最もシンプルな方法ですが、
JSDeferredとは。JSDeferredが解決すること
JSDeferredはJavaScript上の、
詳しいことはあとあと説明しますが、
- コンパクトであること
- 単純にコード行数が少ないということです。
- スタンドアローンで動くこと
- 他のどんなライブラリやフレームワークにも依存せずに動くということです。実際、
JSDeferred の基本機能は setTimeout の挙動のみに依存しています。 - 書きやすいこと
- コールバックによる非同期処理がめんどうくさくて作ったものなので書きやすくないと意味がありません。
JSDeferred自体のコードを読みとくときや、
JavaScriptにおける非同期処理の問題点
最初、
例えば以下のようなコードを考えてみます。最終的に foo.
http.get("/foo.json", function (dataOfFoo) {
http.get("/bar.json", function (dataOfBar) {
http.get("/baz.json", function (dataOfBaz) {
alert([dataOfFoo, dataOfBar, dataOfBaz]);
});
});
});
このようにだんだんと関数のネストが深くなっていきます。この程度ならまだいいですが、
var wants = ["/foo.json", "/bar.json", "/baz.json"];
正直めんどうくさくありませんか?
このように、
JSDeferredを使う
JSDeferredは、
例えば、
// http.get は URI をとって Deferred を返す関数
var results = [];
next(function () {
return http.get("/foo.json").next(function (data) {
results.push(data);
});
}).
next(function () {
return http.get("/baz.json").next(function (data) {
results.push(data);
});
}).
next(function () {
return http.get("/baz.json").next(function (data) {
results.push(data);
});
}).
next(function () {
alert(results);
});
少々長くなりましたが、
var wants = ["/foo.json", "/bar.json", "/baz.json"];
var results = [];
loop(wants.length, function (i) {
return http.get(wants[i]).next(function (data) {
results.push(data);
});
}).
next(function () {
alert(results);
});
この時点でかなり簡潔になりましたし、
parallel([
http.get("/foo.json"),
http.get("/bar.json"),
http.get("/baz.json")
]).
next(function (results) {
alert(results);
});
このように、
ちなみに
JSDeferredはjAutoPagerize[1]を作る過程で生まれたいくつかの欲求を解決するために作られました。そのときは、キャッシュを透過的に実装したい、というのが一番の目的でしたが、仕組みを作っているうちに一般化したくなったためにJSDeferredとして作りはじめました。JSDeferredは何を解決しないか
- JSDeferredはブラウザ間の挙動の差を吸収するためのライブラリではない
- JSDeferredは非同期処理の
「書き方」 を変えるだけ
クロスブラウザのためのライブラリではない
JSDeferredは単機能なライブラリであって、
役割が違うものなので、
「書き方」を変えるだけ
JSDeferredは基本的には
コールバックを受け取る、
これを解決して、
今回はJavaScriptにおける非同期処理の確認と、