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をコピーしました