トップページに戻る
Javascript 非同期関数とPromiseオブジェクト
JavascriptはWebアプリで使われるという特徴から、ネットワーク通信を行う場合があります。
- 通信中にアプリの動作をロックしないよう、基本的に通信作業は非同期関数
(aync function) で行われます。
- 以下にまとめるように、非同期関数はかならず Promizeオブジェクトを返します。
- 通信が成功した場合、失敗した場合は、メソッドチェーンで取得して処理することになります。
- awaitを使うことで、非同期関数の処理終了を待つことができ、同期関数的に使えます。
ただし、awaitが使えるのはasync関数内のみであること、コードによってはPromiseの値が確定しない状態で処理を行うリスクがあるので注意が必要。
また、awaitの多用は、Webアプリの動作をロック・遅延するため、推奨されません。
- async 関数を呼び出した直後の動作
・ 非同期関数 afunc() を呼び出すと、関数内の処理が実行される前に、Promise
オブジェクトが即座に返される。
・ このため、afunc()
の実行が完了するのを待たずに、次の処理に進むことができる。
・ async関数のreturn値は、awaitで取得できる。
・ 一方で、
例:
async function afunc() {
console.log("処理開始");
await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待機
console.log("処理終了");
return "結果";
}
const promise = afunc(); // ここで Promise が即座に返される
console.log(promise); // 出力: Promise { <pending> }
const result = await afunc(); //
成功した場合はreturn値をうけとる。失敗した場合は例外を出すので、try~catchで処理する
console.log(result); // 出力: "結果"
awaitの例外処理:
async function afunc() {
throw new Error("エラーが発生しました"); // 明示的にエラーをスロー
}
async function main() {
try {
const result = await afunc(); // エラーがスローされる
console.log(result);
} catch (error) {
console.error("捕捉したエラー:", error.message); // 出力: "捕捉したエラー: エラーが発生しました"
}
}
- メソッドチェーン:
Promiseの状態や値を利用する唯一の方法
Promise
オブジェクトの状態や結果を直接確認できないので、then/catchで値を取得する。
例:
const promise = afunc();
promise
.then(value => console.log("成功:", value)) // 成功した場合の処理。valueにはreturn値が入る
.catch(error => console.log("失敗:", error)); // エラー時の処理。errにはasync関数内部でthrowされたエラーやPromise.refect()などのエラー情報です
- 非同期関数を同期関数として利用する
・ awaitで終了を待つ
・ awaitはasync関数内部でしか使えない
・ 関数内部で全ての処理を終える場合は、その関数はasync関数でなくてもよい
- Promiseは、async 関数内部の処理が終了し、値を返したり、エラーをスローする準備ができるまで「未解決(pending)」の状態になる。
- Promise の値が確定する場面
・ async 関数の中で、最終的に return 文が実行されるか、エラーがスローされると Promise が「確定(fulfilled または rejected)」する
・ 成功した場合(return 文を通る場合): Promise の状態は fulfilled に変わり、返り値が Promise の解決値(value)になる
・ 失敗した場合(例: throw 文やエラー発生): Promise の状態は rejected に変わり、エラーが Promise の拒否理由(reason)になる
例:
async function afunc() {
return "結果"; // ここで Promise が解決される
}
afunc().then(value => {
console.log(value); // 出力: "結果"
});
- Promise の状態変更のタイミング
Promise の状態(pending, fulfilled, rejected)は、以下の条件で変化します:
・ pending(未解決): async 関数を呼び出した直後の状態
・ fulfilled(解決): 関数内の処理が完了し、return
文が実行された瞬間
・ rejected(拒否): エラーがスローされた瞬間
例(状態変化の流れ):
async function afunc() {
console.log("処理中...");
await new Promise(resolve => setTimeout(resolve, 1000)); // 1秒待機
console.log("解決します!");
return "結果";
}
const promise = afunc(); // Promise が返される(未解決状態)
promise.then(value => {
console.log("Promise解決:", value); // 1秒後に "Promise解決: 結果"
}).catch(error => {
console.log("Promise拒否:", error);
});