JavaScriptのFetch API:知っておきたいこと

Fetch APIが、Promiseベースの構文と効率的なエラー処理を使用してJavaScriptのHTTPリクエストを簡略化する方法を説明します。
5 min read
Fetch API in JavaScript blog image

Fetch APIは、Promiseベースの構文を使用してHTTPリクエストを簡略化する最新のJavaScriptインターフェースです。これにより、コードがより簡潔で使いやすくなります。Fetch APIを使用すると、ページ全体をリロードしなくてもサーバーにデータをリクエストできるため、アプリケーションの速度が向上し、よりインタラクティブ性になります。GET、POST、PUT、またはDELETEリクエストを簡単に送信して、さまざまなAPIとやりとりできます。Fetch APIを使用すると、さまざまなタイプのデータやHTTPメソッドを簡単に処理できます。リクエストヘッダーのカスタマイズとさまざまなコンテンツタイプの管理が簡単になり、さまざまなサービスとシームレスに連携できるようになります。

この記事では、Fetch APIの使用方法、Webアプリケーションにとってのメリット、安全で効率的なデータ処理を実現するためのプロキシの使用方法について説明します。こちらのおすすめプロキシプロバイダーのリストをチェックして、Bright DataがNo.1の選択肢である理由をご確認ください。

Fetch APIについて

Fetch APIは、サーバーにリクエストを送信してpromiseを返すことで、非同期のHTTPリクエストを行うために使用されます。このpromiseは、利用可能になった時点でレスポンスデータで解決されます。JavaScript開発においてFetch APIを使用すると、アプリケーションがページを再ロードせずにサーバーと通信できるようになるため、HTTPリクエスト(例:GET、POST、PUT)を通じてサーバーと動的にやり取りできるようになります。Fetch APIのメリットは次のとおりです。

  • Promiseを使用して簡略化された構文:Fetch APIは、Promiseを使用してXMLHttpRequestの複雑さを排除し、よりクリーンで読みやすいコードを書くことができます。
  • さまざまなデータ形式をサポート:JSON形式、テキスト形式、BLOB形式を使用できるため、さまざまなレスポンスタイプを簡単に解析して処理できます。
  • ストリームオブジェクトとレスポンスオブジェクトを提供:読み取り可能なストリームを使用してレスポンスの精査、変更を行い、アプリケーションに合わせてデータ取得方法を調節できます。
  • エラー処理の改善:FetchはデフォルトでHTTPエラーステータスコードに対してエラーを発生させませんが、より明示的なレスポンスチェックを行うことができます。
  • 複雑さを抑えたコールバック:多数のコールバックを記述することなく、.then().catch()、またはasync/awaitを使用して、リクエストが完了したタイミングを知ることができます。

Fetch APIを使用する利点を確認できたところで、次はその主な特徴と機能を見てみましょう。

非同期操作

Fetch APIは非同期的で、サーバーレスポンスが使用可能になるとPromiseが解決されます。これにより、ユーザーのUIをブロックすることなく、スムーズなユーザーエクスペリエンスを提供できます。いくつか例を見てみましょう。

GETリクエスト

Fetch APIを使用してGETリクエストを送信する方法の例は次のとおりです:

fetch('https://jsonplaceholder.typicode.com/posts')
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then((data) => {
    console.log('Data fetched:', data);
  })
  .catch((error) => {
    console.error('Fetch error:', error);
  });

このスニペットでは、Fetch APIがjsonplaceholder.typicode.comから投稿を取得します。Fetch APIはresponse.okを使用してレスポンスに問題がないかどうかを確認し、問題がある場合はエラーを投げます。次にresponse.json()を使用してJSONへのレスポンスを解析します。ネットワークの問題、不適切な形式のレスポンス、解析の失敗など、すべてのエラーは.catch()ブロックで処理されます。

POSTリクエスト

Fetch APIを使用してPOSTリクエストを送信する方法は次のとおりです:

fetch('https://jsonplaceholder.typicode.com/posts', {
  method: 'POST',
  headers: {
    'Content-type': 'application/json; charset=UTF-8',
  },
  body: JSON.stringify({
    title: 'New Post',
    body: 'Hello World! This is a test.',
    userId: 1,
  }),
})
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then((data) => {
    console.log('New Post created:', data);
  })
  .catch((error) => {
    console.error('Fetch error:', error);
  });

ここでは、Fetch APIはPOSTメソッドを使用して新しいリソースを作成するリクエストを送信します。POSTリクエストはGETリクエストと似ていますが、POSTリクエストにはAPIがJSONデータを送信していることをサーバーに通知するヘッダーが含まれています。実際のJSONデータはボディキーに入ります。

APIとの統合

Fetch APIを使用して、チャート、ダッシュボード、またはその他のデータ駆動型機能のデータの取得などのリクエストを、パブリックAPIまたはプライベートAPIに送信できます。これにより、WebアプリケーションはPromiseベースのフローを使用して外部サービスと通信し、リクエストとレスポンスを処理できます。

OpenWeatherMap APIから気象データを取得する方法の基本的な例は次のとおりです。

const city = "London,uk";
const apiKey = "YOUR_API_KEY";
const url = `https://api.openweathermap.org/data/2.5/weather?q=${city}&APPID=${apiKey}`;

fetch(url)
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error! Status: ${response.status}`);
    }
    return response.json();
  })
  .then((weatherData) => {
    console.log("Weather data for London:", weatherData);
  })
  .catch((error) => {
    console.error("Error fetching weather data:", error);
  });

YOUR_API_KEYを実際のAPIキーに置き換えます。

このコードはOpenWeatherのAPIを使用してロンドンの気象データを取得します。WeatherDataオブジェクトには、温度、湿度、気象条件などの詳細が含まれており、これらをUIに統合できます。

ターミナルまたはシェルから(node filename.jsコマンドを使用して)このコードを実行すると、次のような出力が表示されるはずです。

Weather data for London: {
  coord: { lon: -0.1257, lat: 51.5085 },
  weather: [
    {
      id: 804,
      main: 'Clouds',
      description: 'overcast clouds',
      icon: '04d'
    }
  ],
  base: 'stations',
  main: {
    temp: 273.42,
    feels_like: 273.42,
    temp_min: 272.59,
    temp_max: 274.87,
    pressure: 1021,
    humidity: 87,
    sea_level: 1021,
    grnd_level: 1016
  },
  visibility: 10000,
  wind: { speed: 0.51, deg: 0 },
  clouds: { all: 99 },
  dt: 1736525048,
  sys: {
    type: 2,
    id: 268730,
    country: 'GB',
    sunrise: 1736496173,
    sunset: 1736525567
  },
  timezone: 0,
  id: 2643743,
  name: 'London',
  cod: 200
}

アプリでは、外部データを取り込むために外部APIとのやり取りが必要になることがよくあります。したがって、スケーラブルなWebアプリケーションの構築にあたっては、外部サービスとの統合にクリーンで一貫したアプローチを採用することが重要です。

エラー処理

XMLHttpRequestのような古いAJAXメソッドでは、ネットワークエラーを管理するために複数のイベントハンドラーを設定する必要がありましたが、FetchはPromiseと単一の.catch()ブロックを使用してエラー処理を簡素化します。FetchがPromiseを拒否するのは、ネットワークエラー(インターネット接続がない)が発生した場合だけです。404500のようなHTTPエラーコードではエラーは発生しません。これらのエラーのいずれかが発生したかどうかを確認するには、response.okを手動で確認する必要があります。response.okfalseの場合、サーバーが200—299の範囲外のステータスで応答したことを意味します。次の例は、無効なエンドポイントが原因でリクエストが失敗した場合、Fetchがどのようにエラーを処理するかを示しています。

fetch('https://jsonplaceholder.typicode.com/invalid-endpoint')
  .then((response) => {
    if (!response.ok) {
      throw new Error(`Failed to fetch. Status: ${response.status}`);
    }
    return response.json();
  })
  .then((data) => {
    console.log('This will not run if response is not ok');
  })
  .catch((error) => {
    console.error('Network or response error:', error.message);
  });

このコードを実行すると、Networkまたはレスポンスエラー:取得できませんでした。ステータス:404という出力メッセージを受け取ります。コードは!response.okをチェックし、エンドポイントが存在しないためエラーが返されます。

Fetch APIでのプロキシの使用

プロキシにより、セキュリティ、スケーラビリティ、位置情報機能を強化して、Fetch APIの機能を強化できます。プロキシはクライアントとインターネットの間で仲介役として機能し、一意のIPアドレス、追加のセキュリティ階層、より柔軟なリソース取得方法を提供します。Fetchでプロキシを使用すると、データ抽出やWebスクレイピングアクティビティ中に匿名性を獲得できるため、IPアドレスがブロックされるのを防ぐことができます。プロキシを使用する利点としては、他にも次のようなものがあります。

  • セキュリティの強化:プロキシはIPアドレスをマスクするので、IPアドレスが悪意のある攻撃に対して脆弱になるリスクが軽減されます。
  • スケーラビリティ:プロキシはリクエストを複数のIPに分散できるため、レート制限やブロックを防ぐことができます。
  • 位置情報の柔軟性:プロキシは、さまざまなロケーションからHTTPリクエストを送信するために使用されます。これは、特定の地域でしか利用できないコンテンツにアクセスする場合に便利です。

プロキシのタイプ

プロキシにはさまざまなタイプがあり、それぞれ特定の用途に対応しています。これらのプロキシには次のようなものがあります:

  • 住宅用プロキシ:このプロキシは実際の住宅地のIPを使用します。Webサイトからの信頼度が高いためコストが高くなりますが、ターゲットのWebサイトがデータセンターIPからのトラフィックをブロックした場合の効果も高くなります。
  • ローテーションプロキシ:このプロキシは、リクエストまたはセッションのたびにIPを自動的にローテーションします。サーバーの制限やブラックリストに抵触するリスクを軽減しながら大規模なデータ抽出を行うのに最適です。
  • データセンタープロキシ:このプロキシはデータセンターから提供されます。費用対効果が高く、高速ですが、頻繁に使用するとブロックされます。

Fetch API搭載のBright Dataプロキシ

Bright Dataは、Fetchベースのアプリケーションと統合する高度なプロキシサービスを提供しています。このプロキシにより、住宅用またはデータセンターのオプションを選択することや、エンタープライズレベルのプロジェクト向けにデータ取得機能を拡張すること、自動IPローテーションによる効率的で信頼性の高いデータ収集の恩恵を受けることができます。

Bright DataプロキシをFetch APIと統合する方法は次のとおりです:

import fetch from "node-fetch";
import { HttpsProxyAgent } from "https-proxy-agent";

const proxyHost = "BRIGHT_DATA_PROXY_HOST:PORT";
const proxyUsername = "BRIGHT_DATA_USERNAME";
const proxyPassword = "BRIGHT_DATA_PASSWORD";
const proxyUrl = `http://${proxyUsername}:${proxyPassword}@${proxyHost}`;
const targetUrl = "https://jsonplaceholder.typicode.com/posts";

// Create a proxy agent
const agent = new HttpsProxyAgent(proxyUrl);

fetch(targetUrl, { agent })
  .then((response) => {
    if (!response.ok) {
      throw new Error(`Error fetching data. Status: ${response.status}`);
    }
    return response.json();
  })
  .then((data) => {
    console.log("Data fetched via proxy:", data);
  })
  .catch((error) => {
    console.error("Proxy fetch error:", error);
  });

このコードは、fetchHTTPSProxyAgentを使用し、特定のプロキシを介してリクエストを送信します。次に、プロキシの詳細を定義し、プロキシエージェントを作成します。fetchもプロキシを使用してターゲットURLからデータを取得します。

プロキシを設定するには、node-fetchからFetch APIを使用する必要があります。詳細については、node-fetchのドキュメントを参照してください。このコードは、選択したプロキシによって異なる場合があります。最新情報については、Bright Data公式ドキュメントを参照してください。

Fetch APIのベストプラクティス

Fetch APIリクエストを行うときは、効率とパフォーマンスを向上させるために次のベストプラクティスに従ってください。

レスポンスのキャッシュ

サーバーへの負荷を軽減し、全体的なユーザーエクスペリエンスを向上させるには、頻繁にリクエストされるデータを保存するキャッシュメカニズムを使用して、サーバー呼び出しの重複を回避できます。ネットワークリクエストを行う前にデータがすでにキャッシュされているかどうかを確認する例は次のとおりです。

const cache = new Map();
async function fetchWithCache(url) {
  if (cache.has(url)) {
    console.log("Fetching from cache:", url);
    return cache.get(url);
  }
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    cache.set(url, data);
    console.log("Fetched and cached:", url);
    return data;
  } catch (error) {
    console.error("Fetch error:", error);
    throw error;
  }
}

fetchWithCache("https://jsonplaceholder.typicode.com/posts")
  .then((data) => console.log(data))
  .catch((error) => console.error("Error:", error));

すでにキャッシュされているデータに対する不要なリクエストを防ぐと、パフォーマンスが向上し、ロード時間が短縮されます。

タイムアウト処理

タイムアウトを設定すると、Fetchリクエストが無期限の待機状態になるのを防ぐことができます。AbortControllerを使用して、指定された期間を超えるリクエストをキャンセルできます。次の例では、タイムアウトは3秒に設定されていますが、デフォルトのタイムアウト値は5秒です。

async function fetchWithTimeout(url, timeout = 5000) {
  const controller = new AbortController();
  const timeoutId = setTimeout(() => {
    console.warn("Fetch request timed out:", url);
    controller.abort();
  }, timeout);

  try {
    const response = await fetch(url, { signal: controller.signal });
    clearTimeout(timeoutId);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return await response.json();
  } catch (error) {
    console.error("Fetch timeout or error:", error);
    throw error;
  }
}

fetchWithTimeout("https://jsonplaceholder.typicode.com/posts", 3000)
  .then((data) => console.log(data))
  .catch((error) => console.error("Error:", error));

これにより、指定されたタイムアウトを超えるリクエストは、他のエラーを適切に処理しながら中止されます。

リクエストスロットリング

リクエストによるAPIの過負荷を防ぐには、スロットリングを実装してリクエストの頻度を制御する必要があります。そのため、特定の時間枠内に実行されうるリクエストの数を制限する必要があります。次の例では、指定された間隔(limit)ごとに1回だけ関数が実行されることを保証するthrottle関数を作成します。

function throttle(func, limit) {
  let lastFunc;
  let lastRan;
  return function (...args) {
    const context = this;
    if (!lastRan) {
      func.apply(context, args);
      lastRan = Date.now();
    } else {
      clearTimeout(lastFunc);
      lastFunc = setTimeout(function () {
        if (Date.now() - lastRan >= limit) {
          func.apply(context, args);
          lastRan = Date.now();
        }
      }, limit - (Date.now() - lastRan));
    }
  };
}

const throttledFetch = throttle(async (url) => {
  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    console.log("Throttled fetch data:", data);
  } catch (error) {
    console.error("Throttled fetch error:", error);
  }
}, 2000);

throttledFetch("https://jsonplaceholder.typicode.com/posts");
console.log("Fetching again in 2 seconds...");
throttledFetch("https://jsonplaceholder.typicode.com/posts");

ThrottledFetch関数はthrottleユーティリティを使用してAPIリクエストを制御します。これにより、URLからデータを取得するための呼び出しが繰り返されるときに、少なくとも2秒の間隔が確保されます。こうすることで、重複した、または過剰なAPI呼び出しを防ぎ、エラーを処理し、取得したデータをログに記録します。

まとめ

Fetch APIは、最新のWebアプリケーションにおける非同期操作とデータ処理を簡素化します。ただし、大規模なリクエストや地域をターゲットとするリクエストを処理する場合に、IPブロックレート制限、CAPTCHAなどの課題が発生する可能性があります。

Bright DataのScraper APIとScraping Browserは、これらの課題に対する強力なソリューションを提供します。Scraper APIはスクレイピング対策をバイパスすることでシームレスなデータ抽出を可能にし、Scraping BrowserはJavaScriptを多用する動的コンテンツを効率的に処理します。これらのツールにより、最も複雑なWebサイトでも、安全でスケーラブルな、信頼性の高いデータ収集が可能になります。

クレジットカードは必要ありません