🦒
Axiosによるエラーハンドリング:404エラー発生時のリカバリー方法
はじめに
個人開発でWebAPIを叩いときに404エラーが出てしまってAPIの処理が停止してしまいました。
その解決方法をまとめます。
問題が発生した実装
以下のAPIリクエストはメトロポリタン美術館のものになります。
departmentId
はメトロポリタン美術館にある作品の部門(ヨーロッパ絵画やアジアなど)を指定するときに使うものです。
今回はdeparmentId=11
で指定しています。
今回のAPI処理を簡単に書くと、
- 指定した部門に所蔵されてる作品のidを取得する:
getCollectionIds()
- 作品ごとにAPIを叩いて、作品個別の情報を取得する:
getObject()
の2点になります。
以下実際のコード
// 指定した部門に属している作品のidを入れる
const [collections, setCollections] = useState({id: []})
// 作品個別の情報を入れる
const [object, setObject] = useState([])
const getCollectionIds = () => {
axios
.get(
`https://collectionapi.metmuseum.org/public/collection/v1/search?departmentId=11`
)
.then((res) => {
const newCollection = {
id: res.data.objectIDs,
}
setCollections(newCollection)
})
.catch((error) => {
console.log('Error fetching data:', error)
})
}
// getCollectionIdsで取得したidを使って作品個別の情報を取得する
const getObject = async () => {
// 作品個別のAPIリクエスト用のURIを生成
const getApiUrls = collections.id.map(
(id) => `https://collectionapi.metmuseum.org/public/collection/v1/objects/${id}`
)
const requests = getApiUrls.map((url) => axios.get(url))
const responses = await Promise.all(requests)
const data = responses.map((res) => res.data)
setObject(data)
}
この実装方法で試してみると問題が発生しました。
getCollectionIds()
で取得したものの中にデータを持たないものがありました。
{
"message": "Not a valid object"
}
リクエストした先のデータが空だったため404エラーが返ってきて処理が止まってしまいました。
AxiosError {message: 'Request failed with status code 404', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}
エラーハンドリングでデータが空だった時の処理を実装する
404が返ってきたときに処理を止まるのではなく、データが空だったら次の処理に進むようにします。
今回はtry/catch
を使って処理します。
const [collections, setCollections] = useState({id: []})
const [object, setObject] = useState([])
const getObjectIDs = (departmentId) => {
// 略
}
const getObject = async () => {
const getApiUrls = collections.id.map(
(id) => `https://collectionapi.metmuseum.org/public/collection/v1/objects/${id}`
)
// 404が返ってきた時の処理をする
try {
const requests = getApiUrls.map((url) =>
axios.get(url).catch((error) => {
// データが空だったときはnullを返す
if (error.response?.status === 404) {
console.log(`IDが見つかりませんでした: ${url}`)
return null
}
throw error
})
)
const responses = await Promise.all(requests)
// フィルターをかけてnullのデータを取り除く
const data = responses.filter((res) => res !== null).map((res) => res.data)
setObject(data)
} catch (error) {
console.error('Error fetching object data:', error)
}
}
上記のようにエラーハンドリングを書くことで最後まで処理をしてくれます。
Discussion