Async Functionは関数の定義にasync
キーワードをつけることで定義できます。
JavaScriptの関数定義には関数宣言や関数式、Arrow Function、メソッドの短縮記法などがあります。
どの定義方法でもasync
キーワードを前につけるだけでAsync Functionとして定義できます。
// 関数宣言のAsync Function版
async function fn1() {}
// 関数式のAsync Function版
const fn2 = async function() {};
// Arrow FunctionのAsync Function版
const fn3 = async() => {};
// メソッドの短縮記法のAsync Function版
const object = {
async method() {}
};
これらのAsync Functionは、次のこと以外は通常の関数と同じ性質を持ちます。
-
Async Functionは必ずPromiseを返す
-
Async Function内では
await
式が利用できる
Async Functionとして定義した関数は必ずPromise
インスタンスを返します。
返されるPromise
インスタンスの状態は関数の返り値によって異なり、次の3つのケースが考えられます。
-
Async FunctionはPromise以外の値をreturnした場合、その返り値をもつFulfilledなPromiseを返す
-
Async FunctionがPromiseをreturnした場合、その返り値のPromiseをそのまま返す
-
Async Function内で例外が発生した場合は、そのエラーをもつRejectedなPromiseを返す
これらの挙動はPromise#then
メソッドの返り値とそのコールバック関数が返す値の関係とほぼ同じです。
具体的な例を順番に見ていきます。
まず、Async FunctionはPromise以外の値をreturnした場合、その返り値で解決されるFulfilledなPromiseを返します。
これは、返した値がPromise.resolve
されているのとほとんど同じ感覚です。
// `Promise.resolve(undefined)`を返したのと同じ
async function resolveUndefined() {
// 何も値を返さない場合は`undefined`を返すのと同じ
}
resolveUndefined().then((value) => {
console.log(value); // => undefined
});
// `Promise.resolve("値")`を返したのと同じ
async function resolveFn() {
return "値";
}
resolveFn().then((value) => {
console.log(value); // => "値"
});
次に、 Async FunctionがPromiseをreturnした場合、その返り値のPromiseをそのまま返します。
これは、Promise#then
メソッドでRejectedなPromiseを返すことで、throw
文を使わずにPromiseをrejectする方法と同じです。
// resolveFnは**Fulfilled**なPromiseインスタンスを返している
// Async Functionは自動的にPromiseを返すので、単に値を返しても同じ
async function resolveFn() {
return Promise.resolve("値");
}
resolveFn().then((value) => {
console.log(value); // => "値"
});
// rejectFnは**Rejected**なPromiseインスタンスを返している
async function rejectFn() {
return Promise.reject(new Error("エラーメッセージ"));
}
rejectFn().catch((error) => {
console.log(error.message); // => "エラーメッセージ"
});
最後に、Async Function内で例外が発生した場合は、そのエラーをもつRejectedなPromiseを返します。
これは、Promise内での処理が自動的にtry…catch
されているのと同じで、Async Functionでも例外が発生した場合は自動的にキャッチされます。
// exceptionFnは例外を投げている
async function exceptionFn() {
throw new Error("例外が発生しました");
// 例外が発生したため、この行は実行されません
}
// Async Functionで例外が発生するとRejectedなPromiseが返される
exceptionFn().catch((error) => {
console.log(error.message); // => "例外が発生しました"
});
どの場合でも、Async Functionは必ずPromiseを返すことがわかります。 このようにAsync Functionを呼び出す側から見れば、Async FunctionはPromiseを返すただの関数と何も変わりません。