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;
以上!! これでちょっと共通化が楽になる(*´ω`*)