JavaScriptのAPI呼び出しで絶対につまずく3つのポイントを解説します

javascript icon
JavaScript

API呼び出しで「なんか動かない...」と悩んだことはありませんか?

こんにちは、とまだです。

実はみんな同じところでつまずくんです。私も最初はCORSエラーで半日悩んだりしていました。

でも大丈夫です。

今回は現役のエンジニア、そして元プログラミングスクール講師としての経験から、JavaScriptのAPI呼び出しについて解説します。

そもそもAPI呼び出しって何をしているの?

簡単に言うと、API呼び出しとは「他のサーバーにお願いごとをして、結果をもらう」ことです。

日常生活で言うと、レストランで注文するようなものです。

  • メニューを見る(APIドキュメントを確認)
  • 注文する(リクエストを送る)
  • 料理が来る(レスポンスを受け取る)

このやりとりをプログラムで行うのがAPI呼び出しです。

実際のコードで見てみましょう。

// 天気情報を取得する例
fetch('https://api.example.com/weather')
  .then(response => response.json())
  .then(data => console.log(data));

これだけで外部サービスから情報を取得できるんです。

なぜ非同期処理が必要なのか(同期だと困る理由)

ここで疑問に思うかもしれません。

「なんで非同期とか面倒なことするの?」

実は、もし同期処理でAPIを呼び出すと、サーバーからの返事を待っている間、画面が完全に固まってしまうんです。

例えるなら、レジで会計中に店員さんが在庫確認に行って、その間ずっと動けない状態みたいなものですね。

だから非同期処理を使って、「注文だけして、料理ができたら教えて」という仕組みにしているんです。

初心者が必ずつまずく3つのポイント

1. CORSエラー

「Access to fetch at 'xxx' from origin 'yyy' has been blocked by CORS policy」

このエラー見たことありませんか?

CORSは「別のサイトからの呼び出しを制限する」セキュリティの仕組みです。

解決方法:

  • サーバー側で許可設定をする
  • 開発時はプロキシを使う
  • CORSが不要なAPIを選ぶ

2. async/awaitの書き方

Promiseのthen地獄から抜け出すために、async/awaitがあります。

// ❌ これだと読みにくい
fetch(url)
  .then(res => res.json())
  .then(data => {
    fetch(url2)
      .then(res2 => res2.json())
      .then(data2 => {
        // どんどんネストが深くなる...
      });
  });

// ✅ こっちの方がスッキリ
async function getData() {
  const res = await fetch(url);
  const data = await res.json();
  
  const res2 = await fetch(url2);
  const data2 = await res2.json();
  
  // 見やすい!
}

3. エラーハンドリング

APIは必ず成功するとは限りません。

  • サーバーが落ちているかも
  • ネットワークが切れているかも
  • 権限がないかも

だから必ずエラー処理を書きましょう。

async function fetchData() {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error('サーバーエラーです');
    }
    const data = await response.json();
    return data;
  } catch (error) {
    console.error('エラーが発生しました:', error);
    // ユーザーに分かりやすいメッセージを表示
  }
}

実践的なfetchの使い方

では、実際によく使うパターンを見ていきましょう。

GETリクエスト(データを取得)

async function getUsers() {
  const response = await fetch('https://api.example.com/users');
  const users = await response.json();
  return users;
}

POSTリクエスト(データを送信)

async function createUser(userData) {
  const response = await fetch('https://api.example.com/users', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(userData)
  });
  
  const newUser = await response.json();
  return newUser;
}

// 使い方
createUser({
  name: '山田太郎',
  email: 'yamada@example.com'
});

認証付きリクエスト

async function getPrivateData(token) {
  const response = await fetch('https://api.example.com/private', {
    headers: {
      'Authorization': `Bearer ${token}`
    }
  });
  
  return response.json();
}

Axiosを使うメリット

fetchも便利ですが、実務ではAxiosを使うことも多いです。

なぜか?

  • エラーハンドリングが楽
  • リクエスト/レスポンスの変換が簡単
  • 古いブラウザでも動く
import axios from 'axios';

// fetchよりシンプル
const { data } = await axios.get('https://api.example.com/users');

// POSTも簡単
const newUser = await axios.post('https://api.example.com/users', {
  name: '田中花子',
  email: 'tanaka@example.com'
});

実務でよく使うパターン

API呼び出しを関数化する

同じAPIを何度も呼ぶなら、専用の関数を作りましょう。

// api.js
const API_BASE = 'https://api.example.com';

export async function getUser(userId) {
  const response = await fetch(`${API_BASE}/users/${userId}`);
  if (!response.ok) {
    throw new Error('ユーザーが見つかりません');
  }
  return response.json();
}

export async function updateUser(userId, data) {
  const response = await fetch(`${API_BASE}/users/${userId}`, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify(data)
  });
  return response.json();
}

ローディング状態の管理

async function loadData() {
  setLoading(true); // ローディング開始
  
  try {
    const data = await fetchData();
    setData(data);
  } catch (error) {
    setError(error.message);
  } finally {
    setLoading(false); // ローディング終了
  }
}

並列でAPIを呼ぶ

複数のAPIを同時に呼びたいときは、Promise.allを使います。

async function loadDashboard() {
  const [users, posts, comments] = await Promise.all([
    fetch('/api/users').then(r => r.json()),
    fetch('/api/posts').then(r => r.json()),
    fetch('/api/comments').then(r => r.json())
  ]);
  
  // 全部同時に取得できる!
}

よくあるトラブルと解決法

URLの間違い

一番多いのがこれです。スペルミスやスラッシュの付け忘れなど。

// ❌ よくあるミス
fetch('https://api.example.com/user')  // usersじゃないの?
fetch('https://api.example.com//users') // スラッシュ多い
fetch('http://api.example.com/users')  // httpsじゃないの?

JSONのパースエラー

レスポンスがJSONじゃないときにjson()を呼ぶとエラーになります。

const response = await fetch(url);
const contentType = response.headers.get('content-type');

if (contentType && contentType.includes('application/json')) {
  const data = await response.json();
} else {
  const text = await response.text();
}

ネットワークエラー

オフラインやタイムアウトの対策も必要です。

async function fetchWithTimeout(url, timeout = 5000) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => controller.abort(), timeout);
  
  try {
    const response = await fetch(url, {
      signal: controller.signal
    });
    clearTimeout(timeoutId);
    return response;
  } catch (error) {
    if (error.name === 'AbortError') {
      throw new Error('タイムアウトしました');
    }
    throw error;
  }
}

まとめ

JavaScriptのAPI呼び出しで重要なのは、この3つです。

  1. 非同期処理の理解(async/await)
  2. エラーハンドリング
  3. CORSの仕組み

まずは簡単なGETリクエストから始めてみてください。

慣れてきたらPOSTやPUT、認証付きのリクエストにも挑戦してみましょう。

API呼び出しができるようになると、作れるアプリの幅が一気に広がりますよ。

共有:

著者について

とまだ

とまだ

フルスタックエンジニア

Learning Next の創設者。Ruby on Rails と React を中心に、プログラミング教育に情熱を注いでいます。初心者が楽しく学べる環境作りを目指しています。

著者の詳細を見る →