JavaScript | 非同期処理:async / await – await の戻り値

JavaScript JavaScript
スポンサーリンク
スポンサーリンク

await の戻り値を一言でいうと

await の「戻り値」は、
「Promise が resolve(成功)したときに渡される“中身の値”」 です。

const result = await somePromise; と書いたとき、
result には Promise そのものではなく、その Promise が解決したときの値 が入ります。

ここが重要です。
await が返してくるのは Promise ではありません。
「Promise の箱のフタを開けて、中から取り出した中身」 です。
この感覚をしっかり持っておくと、非同期処理のコードがかなりスッキリ理解できるようになります。


基本:resolve の値がそのまま await の戻り値になる

シンプルな Promise と await の対応

まず、小さな Promise を自分で作ってみます。

function getNumber() {
  return new Promise(resolve => {
    resolve(42);
  });
}
JavaScript

この getNumber() は「いつか 42 を渡してくれる Promise」を返します。

これを await してみましょう。

async function run() {
  const value = await getNumber();
  console.log(value); // 42
}
JavaScript

ここでの流れはこうです。

  1. getNumber() は Promise を返す
  2. await getNumber() は、その Promise の完了(resolve)を待つ
  3. resolve されたときの値 42 が、await の戻り値になる
  4. その値が value に代入される

つまり、

「Promise.resolve(42)」
↓
「await」
↓
「42 が手元に来る」

というイメージです。

実際に console.log してみると違いが分かる

違いを並べて見てみます。

async function run() {
  const promise = getNumber();      // Promise
  const value   = await getNumber(); // 42

  console.log("promise:", promise);
  console.log("value:", value);
}
JavaScript

promise は Promise のオブジェクト(箱)。
value は中身の 42 です。

ここが重要です。
await の戻り値は「Promise の中身」。
「箱そのもの」が欲しいなら await しない、「中身」が欲しいなら await する。
“箱か中身か” を常に意識すると、await の使い方で迷いにくくなります。


実用例:API のレスポンスと await の戻り値

fetch の例で確認してみる

fetch は「レスポンスオブジェクトを resolve する Promise」を返します。

async function fetchJson(url) {
  const response = await fetch(url);     // await の戻り値は Response オブジェクト
  const data = await response.json();    // await の戻り値は パース済みの JSON データ
  return data;
}
JavaScript

ここでは、

await fetch(url) の戻り値 → Response
await response.json() の戻り値 → 解析済みの JS オブジェクト(あるいは配列など)

という風に、「Promise の中身」がそのまま受け取れています。

もし await を付けなかったらどうなるか。

async function fetchJson(url) {
  const responsePromise = fetch(url);
  console.log(responsePromise); // Promise オブジェクト

  // const response = await responsePromise;  // ← ここで初めて中身を取り出せる
}
JavaScript

ここが重要です。
「Promise を返す関数」を呼び出した時点では「箱」しか手に入りません。
await を使うことで、「箱が完了したタイミングで中身をちょうどいい形で受け取る」ことができる。
await の戻り値は、まさにその“ちょうどいい中身”です。


エラー(reject)のとき、await の戻り値はどうなるか

reject されたときは「戻り値」ではなく「例外」が飛ぶ

await が「戻り値」を返すのは、Promise が「resolve(成功)」したときだけです。

Promise が reject された場合、
await は値を返してくれません。
代わりに、その場でエラー(例外)が投げられます。

function failAfter1sec() {
  return new Promise((_, reject) => {
    setTimeout(() => {
      reject(new Error("失敗しました"));
    }, 1000);
  });
}

async function run() {
  try {
    const value = await failAfter1sec(); // ここで throw される
    console.log("これは実行されない:", value);
  } catch (err) {
    console.log("エラーをキャッチ:", err.message); // "失敗しました"
  }
}
JavaScript

この場合、

  • await failAfter1sec() の「戻り値」は存在しません
  • 代わりに、throw new Error("失敗しました") と同じ扱いになります

つまり、await の戻り値は
「成功(resolve)のときだけ手に入る」
「失敗(reject)のときは例外になって飛ぶ」
という二段構えです。

ここが重要です。
await を使うと、「成功時の値」は戻り値としてその場で受け取れ、
「失敗時の値」は try / catch で扱うエラーになる。
Promise の resolve / reject を、同期コードの return / throw に対応させてくれるのが await の役割です。


await と「値の型」の関係

await する前と後で「型」がどう変わるか

例えば、こんな関数があったとします。

function getUser() {
  return new Promise(resolve => {
    resolve({ name: "Taro", age: 20 });
  });
}
JavaScript

このとき:

getUser() の戻り値の型 → Promise<{ name: string; age: number }>
await getUser() の戻り値の型 → { name: string; age: number }

実際のコードにすると:

async function run() {
  const userPromise = getUser();      // Promise<ユーザー>
  const user        = await getUser(); // ユーザーオブジェクトそのもの

  console.log(userPromise); // Promise
  console.log(user.name);   // "Taro"
}
JavaScript

「await は Promise を“はがす”」というイメージ

型の目線で見ると、await は

Promise<T> → T に変換してくれる演算子

です。

Promise<number> を await すると number
Promise<string> を await すると string
Promise<User> を await すると User

というふうに、
Promise に包まれていたものを一枚はがして“中身の型”にしてくれる と考えてください。

ここが重要です。
await の戻り値を考えるときは、「この Promise は最終的に何を返す Promise なのか?」を意識すること。
その “最終的な中身” がそのまま await の戻り値になる、という対応関係を頭に固定しておくと、型やデータ構造で迷いにくくなります。


特殊なケース:await の引数が「Promise じゃない」とき

非 Promise 値を await した場合

実は、await の後ろが Promise でなくても、文法上は通ります。

async function run() {
  const value1 = await 42;
  const value2 = await "hello";
  console.log(value1, value2); // 42 "hello"
}
JavaScript

これは内部的に

await Promise.resolve(42)
await Promise.resolve("hello")

のように扱われます。
実務でこう書く場面はほぼありませんが、
「await は Promise っぽく扱えるものなら何でも受け取る」とだけ知っておけば十分です。

実用的な意味はあまりないが、頭の片隅に置いておく

あくまで理解用の知識として:

await value; は
「value が Promise ならそれを待ち、中身を返す」
「Promise でなければ、そのまま value を返す」

という挙動を取ります。

ここが重要です。
「await の戻り値」は、基本的に「Promise の中身」。
ただし Promise じゃないものを渡した場合は、「その値自身」が戻り値になる。
実務ではほぼ“Promise の中身を取り出すもの”と考えて問題ありません。


await の戻り値を意識した設計のコツ

「この async 関数は、何を返す関数なのか?」を先に決める

例えば、ユーザー情報を取ってくる async 関数を作るなら、

async function fetchUser() {
  // ...
  return userObject; // await fetchUser() の戻り値になる
}
JavaScript

と書いたとき、
「await fetchUser() の戻り値は userObject だ」と自分に宣言しているのと同じです。

このとき、関数の役割を

「Promise を返すこと」ではなく
「`await されたときに、どんな形の値を返すか」

として設計すると、コードの見通しがかなり良くなります。

途中の await を“つなげる”感覚

async function getUserName() {
  const user = await fetchUser();  // user を取り出す
  return user.name;                // await getUserName() の戻り値は name
}
JavaScript

こうしておけば、

const name = await getUserName();
JavaScript

で、最終的に欲しい name だけを
スッと取り出せます。

ここが重要です。
async 関数や await の設計は、「呼び出し側から見てどんな値が欲しいか」から逆算する。
途中の await たちは、その最終的な戻り値にたどり着くために「Promise を一枚ずつはがしていく」ステップだと捉えると、流れがとてもスムーズに考えられます。


初心者として await の戻り値で本当に押さえてほしいこと

await promise の戻り値は、「その promise が resolve したときの値」。
Promise そのものではなく、「中身」が返ってくる。

Promise の型が Promise<T> なら、await の戻り値は T になる。
「箱(Promise)から中身(値)を取り出す」のが await の役割。

Promise が reject されたとき、await は値を返さず、その場で例外(throw)が発生する。
try / catch で受け止めることで、エラーも同期コードのように扱える。

Promise でない値を await した場合、その値自身が戻り値になる(内部的に Promise.resolve されるイメージ)。
ただし実務では「Promise の中身を取り出すもの」と考えておけば十分。

ここが重要です。
await の戻り値を考えるときは、
“この Promise は最終的に何を返すのか?”
“自分はその中身をどの変数で受け取りたいのか?”
を意識してください。
「箱か中身か」を見失わなくなった瞬間、async / await のコードは一気に読みやすく・書きやすくなります。

もし練習したくなったら、次のようなコードを自分で書いてみてください。

// 1. 数字を受け取って、その2倍を resolve する Promise 関数 doubleAsync(n) を作る。
// 2. それを await して結果を受け取り、さらにその2倍を計算して返す async 関数 quadrupleAsync(n) を作る。
// 3. await quadrupleAsync(5) の戻り値が何になるか、実際に console.log して確かめてみる。
JavaScript

「どの時点で Promise を扱っていて、どの時点で“ただの数値”を扱っているか」を意識しながら書くと、
await の「戻り値」のイメージがかなりクリアに定着していきます。

タイトルとURLをコピーしました