fetch
とは
fetch
とは、簡単に言うとHTTPリクエストを送る関数です。
引数にリクエストを送るURLを入れると、リクエストが送信できます。
fetch('https://example.com')
fetch
関数はプロミスを返します。
そのためawait
と組み合わせて使い、リクエストが完了するまで待機することが多いです。
const response = await fetch('https://example.com')
なお、このプロミスは、リクエストが正常に完了したらResponse
オブジェクトで履行されます。
そのためこのコードでのresponse
にはResponse
オブジェクトが入ります。
例
Response
オブジェクトはいくつかのメソッドとプロパティを持っています。
詳細はResponse
で解説しますが、ここではtext
の使用例を紹介します。
以下はtext
メソッドを使ってレスポンスボディを文字列にし、それをログに出力する例です。
const response = await fetch('https://example.com')
const text = await response.text()
console.log(text) // レスポンスボディを文字列にしたものが出力される
ブラウザから実行した場合、リクエストがCORSポリシーに違反しているという理由でリクエストが拒否されることがあります。
その場合はNode.jsなどのサーバーサイドから実行するか、https://example.comのコンソールから実行してみてください。
Request
Request
オブジェクトはHTTPリクエストを示すオブジェクトです。
これはfetch
の引数に入れたりできます。
const request = new Request('https://example.com')
const response = await fetch(request)
Request
は第一引数にURL1を、第二引数にオプションを取ります。
new Request('ここにURL', {
// ここにオプション
})
fetch
の引数はRequest
のコンストラクタの引数と同じです。
そのためRequest
で紹介する内容はそのままfetch
の引数に流用できます。
options
第二引数のoptions
はオブジェクトになっていて、いくつかのオプションを入れることができます。
全てのオプションはこちらから見れます。
ここでは、よく使いそうなオプションを挙げておきます。
headers
リクエストヘッダを示すオブジェクトが入ります。
これはヘッダー名がキー、ヘッダーの値が値という形式です。
よく使うヘッダーの一つに、'Content-Type': 'application/json'
があります。
これは例えば、POST
リクエストのボディがJSON形式であることを示すのに使います。
await fetch('https://example.com', {
method: 'POST',
// ヘッダーを指定
headers: {
// bodyがJSON形式であることを示す
'Content-Type': 'application/json'
},
// リクエストボディを入れる
body: JSON.stringify({ message: 'Hello World!' })
})
また、ここにはHeader
オブジェクトを入れることもできます。
body
リクエストボディを入れられるオプションです。
これは以下の形式に対応しています。
- 文字列(
string
) Blob
FormData
- etc...
例えば、先ほどのContent-Type
ヘッダーやJSON.stringify
と組み合わせて、JSON形式のリクエストを送ることができます。
// リクエストボディに入れるオブジェクト
const bodyObj = {
username: 'nanasi',
post: {
title: 'Hello World!',
body: 'ここに本文'
}
}
await fetch('https://example.com', {
method: 'POST',
headers: {
// bodyがJSON形式であることを示す
'Content-Type': 'application/json'
},
body: JSON.stringify(bodyObj) // JSON形式の文字列に変換する
})
GET
やHEAD
など、一部のリクエストメソッドではbody
オプションを指定できません。
signal
リクエストを途中で中断させるのに使えます。
HTTPリクエストは実行にそれなりの時間やコストがかかることも多いです。
そのため途中で不要になったリクエストを中断し、リソースの節約を試みることができます。
これにはAbortController
のsignal
を使うことが多いと思います。
// コントローラーを作成
const contorller = new AbortController()
// 通常のリクエスト
const promise = fetch('https://exampel.com', {
signal: controller.signal // シグナルを設定
})
// リクエストを中断する
controller.abort()
// fetchのプロミスがAbortErrorで拒否される
詳細はこちらの記事が参考になると思います。
Response
リクエストのレスポンスを示すオブジェクトです。
これはコンストラクタから生成するというより、fetch
などのAPIから返されるものを使うことが多いと思います。
// Responseオブジェクトが入る
const response = await fetch('https://example.com')
response.ok // true
await response.text() // レスポンスボディの文字列
メソッド / プロパティ
ok
リクエストが成功したかを示すプロパティで、値はboolean
です。
const response = await fetch('https://example.com')
response.ok // true
これはステータスコード(status
)が200
~ 299
ならtrue
、それ以外(404
や500
)ならfalse
になります。
// 存在しないページにリクエストを送る
const response = await fetch('https://example.com/not-found')
response.ok // false
status
リクエストのHTTPステータスコードを示すプロパティです。
ステータスコードには例えば200
(正常に完了)や404
(ページが見つからない)、500
(サーバーエラー)などが挙げられます。
// 存在するページにリクエストを送る
const response = await fetch('https://example.com')
response.ok // true
response.status // 200
// 存在しないページにリクエストを送る
const response = await fetch('https://example.com/not-found')
response.ok // false
response.status // 404
ステータスコード一覧はこのサイトがわかりやすかったです。
text
レスポンスボディを文字列にして返すメソッドです。
このメソッドは文字列で履行されるプロミスを返します。
そのため、then
やawait
とセットで使うことが多いです。
const response = await fetch('https://example.com')
// リクエストが正常に完了したかチェック
if (!response.ok) {
throw new Error(`リクエストが正常に完了しませんでした`)
}
// レスポンスボディを取得
const body = await response.text()
console.log(body) // レスポンスボディが出力される
なお、then
を使ってresponse
変数を省略することもできます。
const body = await fetch('https://example.com')
.then(res => res.text()) // thenを使って一気に処理する
console.log(body) // レスポンスボディが出力される
response.ok
などでのチェックをすっ飛ばして直接レスポンスボディを使いたいときは、この方法を使うと簡潔に書けます。
json
レスポンスボディがJSON形式の場合、json
メソッドを使うことでJavaScriptのオブジェクトとしてボディを取得することができます。
const body = await fetch('https://example.com') // 何かJSONを返すAPI
.then(res => res.json()) // jsonメソッドを使用
console.log(body) // { なんらかのオブジェクト }
これはres.text
で取得したテキストをJSON.parse
を使ってオブジェクトにした場合と同じように動きます。
// JSON.parseを使う場合
const body = await fetch('https://example.com')
.then(res => res.text())
.then(text => JSON.parse(text))
// textを使う場合
const body = await fetch('https://example.com')
.then(res => res.json())
なお、レスポンスボディがJSONでなかった場合、このメソッドはSyntaxError
を投げます。
レスポンスの形式には注意してください。