Axiosからunjs/ofetchに移行する際に、
例外を共通化・独自クラスにしたいなと思い、
いろいろ調べてみたときの備忘録(*´ω`*)
onResponseErrorを利用すればOK
ofetch.create()
を使って、共通的なレスポンスエラーに対し、
onResponseError
で設定してやればいいっぽい。
import { ofetch, type $Fetch, type FetchOptions } from "ofetch"; const $Fetch $fetch = ofetch.create({ onResponseError: ({ response, error, request, options }) => { // Raw Responseから必要な情報を取得する const number statusCode = response.status; const string statusText = response.statusText; const any responseBody = response._data; // 共通エラーでwrap throw new MyError({ statusCode, statusText, responseBody }); } });
レスポンスボディはresponse._data
で取得
エラー時のレスポンスの中身はresponse._data
で取得する
response
は素のFetch APIのRequest/Responseなので、
json()
やtext()
を使えばいいかと思ったけど、
Body is unusable
やBody used already for
などのエラーになる。。
onResponseError: ({ response, error, request, options }) => { // json()やtext()だとエラーになる const any responseBody = response.json(); // or const any responseBody = response.text(); }
response
は一度使われるとresponse.bodyUsed
がtrue
になり、
再度利用するとErrorがthrowされるが、
ofetch側でonResponseError
を呼ぶ前にresponse
を利用しているため。
ofetch側で読み込んだデータはresponse._data
に格納されるため、
そちらを使うようにする。
ofetchでのonResponseError
の呼ばれ方
ofetchの該当箇所はこんな感じになってて、
onResponseError
はレスポンスエラーの加工のみ。
onResponseError
でthrowしなくても、握りつぶすことはできないっぽい。
const $fetchRaw: $Fetch["raw"] = async function $fetchRaw( _request, _options = {} ) { // ... 略 if ( !context.options.ignoreResponseError && context.response.status >= 400 && context.response.status < 600 ) { if (context.options.onResponseError) { await context.options.onResponseError(context as any); } return await onError(context); } return context.response; }; const $fetch = async function $fetch(request, options) { const r = await $fetchRaw(request, options); return r._data; } as $Fetch;
以上!! これでちょっと共通化が楽になる(*´ω`*)