概要
PromiseはモダンJSでコーディングする際の肝の1つです。
Promiseを制するものが、モダンJSを制するものと言っても言い過ぎではないと思います。
ES7では、いよいよasync/awaitが実装されます。
今まで感覚で使っていた部分もあるPromiseを再度学習し直そうと思います。
Promiseとは
- 非同期の処理を分かりやすく制御するオブジェクト
- ES6に追加された機能の1つ
- IE対応用のPolyfillも完備
Promiseの使い方
- Promiseはnewして使う。
- Promiseオブジェクトの第1引数は必ず関数
- Promiseの第1引数の関数はは 成功時の処理 と 失敗時の処理 を実行する引数(関数)を取得できる。
- 成功 -> resolve(渡したい値)
- 失敗 -> reject(渡したい値)
- newされたPromiseは以下の関数を持つオブジェクトを返す
then(onFulfilled,onRejected),catch(onRejected)
- thenでresolveされた時の処理、catchでrejectされた時の処理を受け取る
- thenもcatchも引数を持つ関数を引数に取る
- catchはエラーの処理が明確になるだけでなく、複数の非同期処理のエラーをまとめて制御する為にも使用される
- 基本的には、catchを使って失敗時の処理を記述する
const promise = new Promise((resolve, reject) => {
window.setTimeout(() => {
resolve('OK');
}, 2000);
});
promise
.then((result) => {
console.log(result);
})
.catch((error) => {
console.log(error);
});
Promiseパターン
Promiseを使って同期的に処理
- thenの中でPromiseを返せば、さらにthenを続けて記載する事が可能
- 今回の例では、同期的に処理される。
- func1の非同期処理の完了後、func2がコールバックされて、func2の非同期が完了後、次のthenに移っている。
- Promiseを返さなければ、並列で処理されるthenとなる
const func1 = (num) => {
return new Promise((resolve) => {
window.setTimeout(() => {
resolve(num);
}, 3000);
});
};
const func2 = (num) => {
return new Promise((resolve) => {
window.setTimeout(() => {
resolve(num * num);
}, 2000);
});
};
func1(2)
.then(func2)
.then((result) => {
console.log(result);
})
.catch((e) => {
console.log(e);
});
- コールバック地獄が容易に想像出来るが下記の様な書き方も可能
...
func1(2)
.then((res1) => {
func2(res1)
.then((res2) => {
console.log(res2);
});
});
Promiseを使って並列処理して完了を検知する
- 複数の非同期処理を並列で実行し、全てが完了したら情報を取得する
- 非同期のメリット
-
Promise.all([Promise, Promise...])
を使って、非同期な処理を並列で行い、全てがresolveになるタイミングでthenを取得する。 - 並列処理しているもので1つでもrejectがあれば、catchされる。
const func1 = (num) => {
return new Promise((res) => {
window.setTimeout(() => {
res(num + num);
}, 500);
});
};
const func2 = (num) => {
return new Promise((res, rej) => {
window.setTimeout(() => {
rej(num * num);
}, 2000);
});
};
Promise.all([
func1(2),
func2(3)
])
.then((results) => {
console.log(results);
})
.catch((e) => {
console.log(e);
});
1つでも処理が返ってきたら実行する
-
Promise.race([Promise, Promise...])
を使う事で、resolveもcatchでも何かしら処理が返ってきたら次の処理(thenやcatch)を実行する様に出来る。
const func1 = (num) => {
return new Promise((res) => {
window.setTimeout(() => {
res(num + num);
}, 500);
});
};
const func2 = (num) => {
return new Promise((res, rej) => {
window.setTimeout(() => {
rej(num * num);
}, 2000);
});
};
Promise.race([
func1(3),
func2(3)
])
.then((res) => {
console.log(res);
})
.catch((e) => {
console.log(e);
});
終わり
今回は基本編という事で、Promiseオブジェクトの最低限の知識をまとめました。
次回は、ES7で実装されるasync/awaitを使って、より柔軟にPromiseを使って見たいと思います。