概要
- 非同期処理に少しつまづいたので、調べたことをまとめてみました。
非同期処理
- 同期処理とはソースコードが書かれている順番に実行し、現在の処理が終わるまで次の処理は待機状態にある
- 対して、処理が書かれた順番には依存せず、異なるタイムライン上で実行することを非同期処理という
- サーバとの通信など時間のかかる処理を行う場合にはよく使われる
今回はEcmaScript6で標準化されたPromiseを使って非同期処理とはどのような処理か、どう実装すれば良いか紹介します。
Promise
new Promise(function(resolve, reject) { ... });
- EcmaScript6で実装された非同期処理のためのオブジェクト
- もともとはjqueryやasync.jsなどの方が先で、後から標準化されたらしい
仕様
- 初期化時の引数
-
resolve
: 必須, 成功時に実行する関数 -
reject
: 省略可能, 失敗時に実行する関数
-
- 以下の状態を返す
-
pending
: 未解決(初期値) -
fulfilled
: 無事完了 -
rejected
: 棄却
-
- 処理の結果によって状態が変わる
-
resolve
を実行するとfulfilled
になる -
reject
を実行するとrejected
になる
-
- 処理が終わったらthenが呼ばれる
promise.then(function() { ... })
例1: 仕様と処理の実行順序を理解する
var func = new Promise(
function(resolve, reject) {
setTimeout(
function() {
resolve({"message": "success"});
}, 3000
);
});
console.log("1");
func.then(function(data) {
console.log(data.message);
}, function(error) {
console.log(error.message);
});
console.log("2");
- Promiseによって実行された処理はグローバルの処理とは並行して実行される
-
console.log
の出力は以下のようになる(doAsyncProcess
の処理時間によって前後する)
"1"
"2"
"success/error"
Promiseオブジェクトの連鎖
-
then
,catch
メソッドはPromiseを返却するため、メソッドチェーンを作ることができる
doSomething1()
.then(doSomething2) // doSomething1の結果を受けて実行される
.then(doSomething3)
.then(doSomething4);
複数の非同期処理をまとめて管理
- 複数の非同期処理を並行して実行し、全ての処理が完了したことを前提とした処理を行いたい場合は以下のように
Promise.all
メソッドを用いて実装する
var promises = [
doSomething1(),
doSomething2(),
doSomething3(),
doSomething4()
];
Promise.all(promises)
.then(function(results) {
console.log(results[0]); // doSomething1のresolveに渡された値
console.log(results[1]); // doSomething2のresolveに渡された値
console.log(results[2]); // doSomething3のresolveに渡された値
console.log(results[3]); // doSomething4のresolveに渡された値
}, function(error) {
console.log(error); // 最初にrejectに渡された値
});
Promiseの使い方は大体こんな感じです。jQuery's Deferredや$qはざっと見た感じPromiseと大差ない気がしました。
次回はNode.jsのモジュールとして公開されているasync.jsについて触れようと思います。こちらは値の返し方や処理の実行フローについても細かく使い分けられるようで面白いですね。
以上です。