MochiuWiki : SUSE, EC, PCB
検索
個人用ツール
ログイン
Toggle dark mode
名前空間
ページ
議論
表示
閲覧
ソースを閲覧
履歴を表示
JavaScriptの基礎 - Fetch APIのソースを表示
提供: MochiuWiki : SUSE, EC, PCB
←
JavaScriptの基礎 - Fetch API
あなたには「このページの編集」を行う権限がありません。理由は以下の通りです:
この操作は、次のグループのいずれかに属する利用者のみが実行できます:
管理者
、new-group。
このページのソースの閲覧やコピーができます。
== 概要 == Fetch APIは、ネットワークリクエストを行うためのブラウザ標準のインターフェースである。<br> 従来の <code>XMLHttpRequest</code> と比較して、簡潔なAPIを提供しており、Promiseベースの設計により非同期処理の記述が容易になっている。<br> <br> <code>fetch()</code> 関数は、指定したURLへHTTPリクエストを送信してResponseオブジェクトに解決されるPromiseを返す。<br> GETリクエストによるデータ取得からPOSTリクエストによるデータ送信まで、あらゆるHTTP通信をサポートしている。<br> <br> Fetch APIの使用時において、重要な特性として、HTTPエラー (404や500等) が発生してもPromiseはrejectされないことが挙げられる。<br> Promiseがrejectされるのはネットワークエラーが発生した場合のみであり、HTTPエラーの検出には <code>response.ok</code> プロパティを明示的にチェックする必要がある。<br> <br> リクエストのキャンセルには <code>AbortController</code> を使用する。<br> <code>AbortSignal.timeout()</code> による簡易タイムアウト設定、<code>AbortSignal.any()</code> による複数シグナルの組み合わせも活用できる。<br> <br> Reactの <code>useEffect</code> フック内でFetch APIを使用する場合、コンポーネントのアンマウント時にリクエストをキャンセルするクリーンアップ処理を実装することにより、<br> メモリリークおよびレースコンディションを防止できる。<br> <br> <u>Fetch APIは全ての最新のWebブラウザで対応しているが、Internet Explorerには対応していない。</u><br> <br><br> == fetch()の基本 == ==== 基本構文 ==== <code>fetch()</code> 関数の基本的な構文を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> fetch(url, options) </syntaxhighlight> <br> <center> {| class="wikitable" |+ fetchメソッドの引数 ! 引数 !! 説明 |- | <code>url</code> || リクエスト先のURLを、文字列 または URLオブジェクトで指定する。 |- | <code>options</code> || オプションオブジェクト (省略可能) |} </center> <br> 下表に、<code>options</code> で指定可能なパラメータを示す。<br> <br> <center> {| class="wikitable" |+ optionsで指定可能なパラメータ ! パラメータ !! 説明 |- | <code>method</code> | * HTTPメソッドを指定する。デフォルトは <code>'GET'</code> である。 * 指定可能な値: <code>'GET'</code>, <code>'POST'</code>, <code>'PUT'</code>, <code>'DELETE'</code>, <code>'PATCH'</code> 等 |- | <code>headers</code> | * リクエストヘッダを指定する。 * <code>Headers</code> オブジェクトまたはオブジェクトリテラルで指定できる。 |- | <code>body</code> | * リクエストボディを指定する。<code>GET</code> および <code>HEAD</code> リクエストには指定できない。 * 文字列、Blob、FormData、URLSearchParams等を指定できる。 |- | <code>credentials</code> | * クッキーの送信方法を指定する。デフォルトは <code>'same-origin'</code> である。 * 指定可能な値: <code>'same-origin'</code>, <code>'include'</code>, <code>'omit'</code> |- | <code>mode</code> | * CORSモードを指定する。デフォルトは <code>'cors'</code> である。 * 指定可能な値: <code>'cors'</code>, <code>'no-cors'</code>, <code>'same-origin'</code> |- | <code>redirect</code> | * リダイレクトの処理方法を指定する。デフォルトは <code>'follow'</code> である。 * 指定可能な値: <code>'follow'</code>, <code>'error'</code>, <code>'manual'</code> |- | <code>signal</code> || リクエストをキャンセルするための <code>AbortSignal</code> オブジェクトを指定する。 |} </center> <br> ==== Responseオブジェクト ==== <code>fetch()</code> が返すPromiseは、<code>Response</code> オブジェクトに解決される。<br> <code>Response</code> オブジェクトの主要なプロパティを以下に示す。<br> <br> <center> {| class="wikitable" |+ Responseオブジェクトのプロパティ ! プロパティ !! 説明 |- | ok ||ステータスコードが200〜299の範囲にあるかどうかを示すboolean値である。<br>HTTPエラーの検出に使用する。 |- | status || HTTPステータスコードを示す数値である。<br>(例: 200, 404, 500) |- | statusText || ステータスに対応するテキストを示す文字列である。<br>(例: <code>'OK'</code>, <code>'Not Found'</code>) |- | headers || レスポンスヘッダを含む <code>Headers</code> オブジェクトである。 |- | url || リダイレクト後の最終的なURLを示す文字列である。 |- | redirected || リダイレクトが発生したかどうかを示すboolean値である。 |} </center> <br> ==== レスポンスボディの読み取り ==== <code>Response</code> オブジェクトは、ボディを読み取るための複数のメソッドを提供している。<br> いずれのメソッドもPromiseを返す。<br> <br> <center> {| class="wikitable" |+ レスポンスボディ読み取りメソッド ! メソッド !! 戻り値 !! 用途 |- | <code>response.json()</code> || JavaScriptオブジェクト || JSONレスポンスの読み取り |- | <code>response.text()</code> || 文字列 (UTF-8) || テキストレスポンスの読み取り |- | <code>response.blob()</code> || Blobオブジェクト || 画像・ファイル等のバイナリデータの読み取り |- | <code>response.arrayBuffer()</code> || ArrayBuffer || 低レベルのバイナリデータの読み取り |- | <code>response.formData()</code> || FormDataオブジェクト || フォームデータの読み取り |} </center> <br> <u>※注意</u><br> <u>レスポンスボディは1度だけ読み取り可能である。</u><br> <u>同じレスポンスボディを複数回読み取る必要がある場合は、<code>response.clone()</code> でレスポンスを複製する。</u><br> <br><br> == GETリクエスト == ==== 基本的なGETリクエスト ==== 基本的なGETリクエストの例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const response = await fetch('https://api.example.com/users') const data = await response.json() console.log(data) </syntaxhighlight> <br> <code>fetch()</code> はPromiseを返すため、<code>await</code> を使用することにより、Responseオブジェクトを取得できる。<br> 続いて <code>response.json()</code> を <code>await</code> することにより、JSONをJavaScriptオブジェクトに変換できる。<br> <br> ==== クエリパラメータの付与 ==== クエリパラメータを付与する場合は、<code>URLSearchParams</code> を使用することにより、安全にエンコードできる。<br> <br> <syntaxhighlight lang="javascript"> const params = new URLSearchParams({ page: '1', limit: '10', search: 'javascript' }) const response = await fetch(`https://api.example.com/users?${params}`) const data = await response.json() </syntaxhighlight> <br> <u><code>URLSearchParams</code> を使用することにより、特殊文字や日本語等を含む値も自動的にパーセントエンコードされる。</u><br> <u>文字列連結によるURL構築は特殊文字を含む値でエラーが発生する可能性があるため、<code>URLSearchParams</code> の使用を推奨する。</u><br> <br> ==== ヘッダの設定 ==== 認証トークンや Accept ヘッダ等を設定する例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const response = await fetch('https://api.example.com/users', { headers: { 'Authorization': 'Bearer token123', 'Accept': 'application/json' } }) const data = await response.json() </syntaxhighlight> <br> <code>headers</code> オプションにはオブジェクトリテラルを指定できる。<br> より複雑なヘッダ操作が必要な場合は、<code>Headers</code> オブジェクトを使用することも可能である。<br> <br><br> == POSTリクエスト == ==== JSONデータの送信 ==== JSONデータをPOSTリクエストで送信する例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const response = await fetch('https://api.example.com/users', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ name: 'John', email: 'john@example.com' }) }) const data = await response.json() </syntaxhighlight> <br> <u>JSONデータを送信する場合は、以下に示す事柄に注意する。</u><br> * <u><code>method</code> に <code>'POST'</code> を指定する。</u> * <u><code>headers</code> に <code>'Content-Type': 'application/json'</code> を設定する。</u> * <u><code>body</code> には、JavaScriptオブジェクトを <code>JSON.stringify()</code> で文字列に変換したものを指定する。</u> <br> ==== FormDataの送信 ==== ファイルアップロード等、マルチパートフォームデータを送信する例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const formData = new FormData() formData.append('name', 'John') formData.append('file', fileInput.files[0]) const response = await fetch('https://api.example.com/upload', { method: 'POST', body: formData // Content-Typeは設定しない // Webブラウザが自動的に設定する }) const data = await response.json() </syntaxhighlight> <br> <u><code>FormData</code> を送信する場合は、<code>Content-Type</code> ヘッダを手動で設定しない。</u><br> <u>Webブラウザが自動的に <code>multipart/form-data</code> を設定して、適切なバウンダリ文字列も付加する。</u><br> <br> <u>手動で <code>Content-Type</code> を設定するとバウンダリが欠落し、サーバ側でのパースに失敗する。</u><br> <br><br> == エラーハンドリング == ==== HTTPエラーの処理 ==== Fetch APIの重要な特性として、HTTPエラー (404や500等) が発生してもPromiseはrejectされない。<br> この場合、Promiseは正常に解決されるが、<code>response.ok</code> が <u>false</u> になる。<br> <br> <code>response.ok</code> を使用したHTTPエラーの処理例を以下に示す。<br> <br> <syntaxhighlight lang="javascript"> const response = await fetch('https://api.example.com/users') if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`) } const data = await response.json() </syntaxhighlight> <br> <code>response.ok</code> はステータスコードが200〜299の場合に <u>true</u> となる。<br> <u>HTTPエラーを適切に処理するには、このチェックを明示的に定義する必要がある。</u><br> <br> Promiseがrejectされるのは、サーバに到達できない場合等のネットワークエラーが発生したときのみである。<br> この場合、<u>TypeError</u> がスローされる。<br> <br> <syntaxhighlight lang="javascript"> try { const response = await fetch('https://api.example.com/users') const data = await response.json() } catch (error) { if (error instanceof TypeError) { console.error('ネットワークエラー:', error.message) } } </syntaxhighlight> <br> ネットワークエラーの原因には、インターネット接続の切断、DNSエラー、CORS違反等が含まれる。<br> <br> ==== 包括的なエラーハンドリングパターン ==== HTTPエラーとネットワークエラーの両方を処理する包括的なパターンを以下に示す。<br> <br> <syntaxhighlight lang="javascript"> async function fetchWithErrorHandling(url) { try { const response = await fetch(url) if (!response.ok) { throw new Error(`HTTP error! status: ${response.status}`) } return await response.json() } catch (error) { if (error instanceof TypeError) { console.error('ネットワークエラー:', error) } else if (error.name === 'AbortError') { console.error('リクエストがキャンセルされた') } else { console.error('エラー:', error) } throw error } } </syntaxhighlight> <br> このパターンでは、エラーの種類に応じて以下の分類で処理を行う。<br> <br> <center> {| class="wikitable" |+ エラーの種類と処理の分類 ! エラーの種類 !! 説明 |- | <u>TypeError</u> || ネットワークエラー (接続失敗等) |- | <u>error.name === 'AbortError'</u> || <code>AbortController</code> によるリクエストのキャンセル |- | それ以外 || HTTPエラー等のその他のエラー |} </center> <br><br> == AbortControllerによるリクエストキャンセル == ==== 基本的な使い方 ==== <code>AbortController</code> を使用することにより、進行中のリクエストをキャンセルできる。<br> キャンセル時には <code>AbortError</code> という名前の <code>DOMException</code> がスローされる。<br> <br> <syntaxhighlight lang="javascript"> const controller = new AbortController() // 5秒後にキャンセルする setTimeout(() => controller.abort(), 5000) try { const response = await fetch('https://api.example.com/users', { signal: controller.signal }) const data = await response.json() } catch (error) { if (error.name === 'AbortError') { console.log('リクエストがキャンセルされた') } } </syntaxhighlight> <br> <code>AbortController</code> の <code>signal</code> プロパティを <code>fetch()</code> の <code>signal</code> オプションに渡すことにより、<br> <code>controller.abort()</code> を呼び出したタイミングでリクエストがキャンセルされる。<br> <br> Webブラウザの対応状況: Chrome 66以降、Firefox 57以降、Safari 11以降<br> <br> ==== AbortSignal.timeout ==== <code>AbortSignal.timeout()</code> は、指定したミリ秒後に自動的にタイムアウトするシグナルを生成するスタティックメソッドである。<br> <code>AbortController</code> を手動で作成する必要がなく、タイムアウト処理を簡潔に記述できる。<br> <br> <syntaxhighlight lang="javascript"> const response = await fetch('https://api.example.com/users', { signal: AbortSignal.timeout(5000) }) </syntaxhighlight> <br> タイムアウト発生時には <code>AbortError</code> ではなく、<code>TimeoutError</code> という名前の <code>DOMException</code> がスローされる。<br> これにより、ユーザによる明示的なキャンセル (<code>AbortError</code>) と タイムアウト (<code>TimeoutError</code>) を区別して処理できる。<br> <br> Webブラウザの対応状況: Chrome 94以降、Firefox 103以降、Safari 16.4以降、Edge 94以降<br> <br> ==== AbortSignal.any ==== <code>AbortSignal.any()</code> は、複数のシグナルを受け取り、いずれかが中断されたときに中断する新しいシグナルを生成するスタティックメソッドである。<br> タイムアウトとユーザによるキャンセルを組み合わせる場合等に有用である。<br> <br> <syntaxhighlight lang="javascript"> const controller = new AbortController() const response = await fetch('https://api.example.com/users', { signal: AbortSignal.any([ AbortSignal.timeout(5000), controller.signal ]) }) </syntaxhighlight> <br> 上記の例では、5秒のタイムアウトが発生 または <code>controller.abort()</code> が呼び出されるかのいずれか早い方でリクエストがキャンセルされる。<br> <br> Webブラウザの対応状況: Chrome 123以降、Firefox 121以降、Safari 17.4以降、Edge 123以降<br> <br><br> == Reactでの使用パターン == ==== useEffectでのデータ取得 ==== Reactコンポーネントの <code>useEffect</code> フック内でFetch APIを使用する際の推奨パターンを以下に示す。<br> <br> <syntaxhighlight lang="javascript"> import { useState, useEffect } from 'react' function UserList() { const [data, setData] = useState(null) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) useEffect(() => { const controller = new AbortController() const fetchData = async () => { try { setLoading(true) const response = await fetch('https://api.example.com/users', { signal: controller.signal }) if (!response.ok) throw new Error(`HTTP ${response.status}`) const result = await response.json() setData(result) setError(null) } catch (error) { if (error.name !== 'AbortError') { setError(error.message) } } finally { setLoading(false) } } fetchData() return () => controller.abort() }, []) if (loading) return <div>読み込み中...</div> if (error) return <div>エラー: {error}</div> return <pre>{JSON.stringify(data, null, 2)}</pre> } </syntaxhighlight> <br> <code>useEffect</code> のクリーンアップ関数で <code>controller.abort()</code> を呼び出すことには以下の重要な意義がある。<br> <br> * メモリリークの防止 *: コンポーネントがアンマウントされた後に非同期処理が完了しても、状態の更新が実行されなくなる。 * 不要なリクエストのキャンセル *: コンポーネントがアンマウントされた時点で進行中のリクエストをキャンセルする。 * レースコンディションの防止 *: 依存配列の値が変化して再レンダリングが発生した場合、前のリクエストをキャンセルしてから新しいリクエストを開始する。 <br> <code>AbortError</code> はコンポーネントの正常なライフサイクルの一部であるため、エラーとして扱わないよう <code>error.name !== 'AbortError'</code> でフィルタリングしている。<br> <br><br> == 関連情報 == * [[JavaScriptの基礎 - Promise]] * [[JavaScriptの基礎 - async await]] * [[JavaScriptの基礎 - イベントループ]] <br><br> {{#seo: |title={{PAGENAME}} : Exploring Electronics and SUSE Linux | MochiuWiki |keywords=MochiuWiki,Mochiu,Wiki,Mochiu Wiki,Electric Circuit,Electric,pcb,Mathematics,AVR,TI,STMicro,AVR,ATmega,MSP430,STM,Arduino,Xilinx,FPGA,Verilog,HDL,PinePhone,Pine Phone,Raspberry,Raspberry Pi,C,C++,C#,Qt,Qml,MFC,Shell,Bash,Zsh,Fish,SUSE,SLE,Suse Enterprise,Suse Linux,openSUSE,open SUSE,Leap,Linux,uCLnux,電気回路,電子回路,基板,プリント基板 |description={{PAGENAME}} - 電子回路とSUSE Linuxに関する情報 | This page is {{PAGENAME}} in our wiki about electronic circuits and SUSE Linux |image=/resources/assets/MochiuLogo_Single_Blue.png }} __FORCETOC__ [[カテゴリ:Web]]
JavaScriptの基礎 - Fetch API
に戻る。
案内
メインページ
最近の更新
おまかせ表示
MediaWiki についてのヘルプ
ツール
リンク元
関連ページの更新状況
特別ページ
ページ情報
We ask for
Donations
Collapse