async / await の「async 関数」を一言でいうと
async 関数は、
「中で await が使える “非同期版の関数”」 です。
先に一番大事なポイントだけ言うと:
- 関数の前に
asyncを付けると、その関数は 必ず Promise を返す関数になる async関数の中では、awaitを使って 非同期処理の完了を “同期っぽく” 待てる
ここが重要です。async は「なんか非同期っぽい感じになる魔法」ではなく、
「この関数は Promise を返すよ。その中では await を使ってもいいよ」という“約束の宣言” です。
定義の形と、返り値のルールをしっかり押さえましょう。
async 関数の基本的な定義のしかた
function 文に async を付ける
一番素直な形は、通常の関数の前に async を付ける書き方です。
async function fetchData() {
return "hello";
}
JavaScriptこのとき fetchData() は、
実際には "hello" ではなく「"hello" を解決する Promise」を返します。
const result = fetchData();
console.log(result); // Promise { <fulfilled>: "hello" } のようなもの
JavaScriptasync を付けた瞬間、その関数の返り値は
「生の値」→「Promise に包まれた値」
に変わる、と思ってください。
関数式・アロー関数でも同じ
関数式にも async を付けられます。
const fetchData = async function () {
return "hello";
};
JavaScriptアロー関数の場合も同様です。
const fetchData = async () => {
return "hello";
};
JavaScriptどれも意味は同じで、
「呼び出すと Promise を返す関数」 を定義しているだけです。
ここが重要です。async は「関数の中身」ではなく
「その関数の“型”」を変えます。
どの書き方であっても、async を付けたら「Promise を返す関数」になる と覚えてください。
async 関数の返り値のルール(ここをちゃんと深掘る)
return した値は Promise に自動で包まれる
async 関数の中で return した値は、
自動的に Promise.resolve(値) された形になります。
async function getNumber() {
return 42;
}
getNumber().then(value => {
console.log(value); // 42
});
JavaScriptgetNumber() は 42 ではなく Promise<number> を返しますが、then の中では普通に 42 が取れます。
例:普通の関数との違い
普通の関数:
function normal() {
return 42;
}
const v1 = normal(); // v1 は 42(number)
JavaScriptasync 関数:
async function asyncFunc() {
return 42;
}
const v2 = asyncFunc(); // v2 は Promise(中身は 42)
JavaScript見た目は似ていますが、
呼び出した結果の「型」が根本的に違う ことに注意してください。
何も return しない場合
async 関数で何も返さない(return しない)場合、undefined を解決する Promise になります。
async function doSomething() {
console.log("処理中...");
}
doSomething().then(value => {
console.log("then の value:", value); // undefined
});
JavaScriptここが重要です。async 関数の返り値は「Promise である」という約束が絶対です。
return した値は必ず Promise に包まれ、
何も return しなくても Promise<void> 的なものが返ります。
この “Promise を返す関数” だからこそ、await で待てるようになります。
async 関数内での await のイメージ
await で「Promise の結果を待ってから次へ進む」
async 関数の中では、await を使って
Promise が完了するまで「そこで一旦止まり」、
結果を普通の値として受け取れます。
例えば、fetch(HTTPリクエスト)を使う例:
async function fetchJson(url) {
const response = await fetch(url); // ここでレスポンスを待つ
const data = await response.json(); // JSON 変換を待つ
return data; // data を解決する Promise が返る
}
JavaScriptこの fetchJson は
- 呼ぶ側から見ると:「Promise を返す関数」
- 中の書き方は:「一見同期っぽく、上から順に進むコード」
になっています。
await が使えるのは async 関数の中だけです。
(トップレベル await が使える環境もありますが、まずは「async の中で使う」と覚えれば十分です)
ここが重要です。async で関数を定義する本当の意味は、「この関数の中では await で Promise を“待てる” ようにすること」。
外から見れば Promise を返す関数、
中から見れば “同期っぽく書ける非同期関数”。
この二重構造をイメージできると、一気に理解が進みます。
例題:async 関数の定義と使い方を具体的に見る
例1:1 秒待ってから値を返す async 関数
まず、1 秒後に解決される Promise を返す関数を作ります。
function wait1sec() {
return new Promise(resolve => {
setTimeout(() => {
resolve("1秒経ちました");
}, 1000);
});
}
JavaScriptこれを await で使う async 関数を定義します。
async function run() {
console.log("開始");
const message = await wait1sec(); // ここで 1 秒待つ
console.log(message); // "1秒経ちました"
console.log("終了");
}
JavaScriptrun() を呼ぶと、
「開始 → (1秒後)→ 1秒経ちました → 終了」
という順でログが出ます。
run 自体は Promise を返す関数です。
const p = run();
console.log(p); // Promise { <pending> } のようなもの
JavaScript例2:async 関数の定義と then の両方を組み合わせる
run を await する側がさらに別の async 関数だとしたら:
async function main() {
await run(); // run の完了を待つ
console.log("main 完了");
}
JavaScriptあるいは Promise として扱っても構いません。
run().then(() => {
console.log("run が終わったので then");
});
JavaScriptここが重要です。
async 関数は「中では await が使える」けれど、
「外から見ればただの Promise を返す関数」です。
だから、await asyncFunc() と書いてもいいし、asyncFunc().then(...) と書いてもいい。
Promise の世界と async/await の世界は、同じ土台の上に立っています。
async 関数のエラーハンドリング(定義とセットで意識してほしい)
throw したエラーは Promise の reject になる
async 関数の中で throw すると、
その関数の Promise は reject されます。
async function failExample() {
throw new Error("何かがうまくいかなかった");
}
failExample()
.then(() => {
console.log("ここは実行されない");
})
.catch(err => {
console.log("エラー:", err.message); // "エラー: 何かがうまくいかなかった"
});
JavaScriptawait 側では try / catch で受け止める
await を使う側では、
通常の同期コードと同じように try / catch でエラーを扱えます。
async function main() {
try {
await failExample();
console.log("ここは実行されない");
} catch (err) {
console.log("catch で受け止めた:", err.message);
}
}
JavaScriptここが重要です。
async 関数の定義をしたら、
「この関数が失敗することはあるか? そのとき何を throw するか?」までセットで設計するのがとても大事です。
外から見れば、「resolve か reject か」の Promise になるので、
成功値・失敗値の形をきちんと決めておくことが、後々の読みやすさと扱いやすさにつながります。
初心者として async 関数の定義で本当に押さえてほしいこと
async を関数の前に付けると、その関数は必ず Promise を返す。return 値 は、内部的には Promise.resolve(値) になる。
async 関数の中でだけ await が使える。await promise は、Promise の完了を待って「その結果の値」を返す。
何も return しない async 関数も、
外から見れば Promise<void> 的なもの(中身は undefined)を返している。
async 関数内で throw したエラーは、その Promise の reject になる。
await する側は try / catch で同期コードのようにエラー処理ができる。
ここが重要です。
async 関数の定義は、
「この処理は非同期だよ。だから Promise を返すよ。その中では await で綺麗に書けるよ」という宣言です。
“Promise を返す関数” を自分で定義できるようになると、
非同期処理を「中身はきれいな手続き」「外側は Promise」として整理できるようになって、
コード全体の見通しが一気に良くなります。
最後に、小さな練習として、次の 2 つを自分で書いてみてください。
// 1. 2 秒待ってから "done" を返す async 関数 delayDone を定義し、
// それを await する async 関数 main を作って、結果を console.log する。
// 2. Promise を直接 new で作る関数と、
// 同じことをする async 関数をそれぞれ書いて、
// 「外から見たときにどちらも Promise である」ことを確かめてみる。
JavaScript「async の有無で何が変わるのか」を、
自分の手で書いて・ログを見て・体で覚えていくと、
非同期処理の感覚がぐっと掴みやすくなります。

