通常のfetchの例
コメントで問題点を記載
fetch("https://example.com/api", {
method: "POS", // 1. エディタ上でエラーにならない
headers: {
"Content-Typ": "application/jso", // 2. エディタ上でエラーにならない
Authorization: `Bearer ${"foo"}`,
},
credentials: "include",
mode: "cors",
body: JSON.stringify({ name: "bar" }), // 3. JSON.stringify が必要
})
.then((resp) => {
if (resp.ok) return resp.json();
// 4. then なのにエラー処理が入る
switch (resp.status) {
case 500:
location.href = "/500.html";
return;
case 404:
location.href = "/404.html";
return;
case 401:
location.href = "/login.html";
return;
default:
alert(resp.statusText);
}
})
.then(({ id }: { id: number }) => console.log(id))
.catch((e) => alert(e.message));
解決
コード補完が効くので、ミスなく快適に
fetcha("https://example.com/api")
.contentType("application/json")
.header("Authrization", `Bearer ${"foo"}`)
.credentials("include")
.mode("cors")
.post({ name: "bar" })
.then((resp) => resp.toJson<{ id: number }>())
.then(({id}) => console.log(id))
.catch((e: FetchaError) => {
switch (e.status) {
case 500:
location.href = "/500.html";
return;
case 404:
location.href = "/404.html";
return;
case 401:
location.href = "/login.html";
return;
default:
alert(e.message);
}
});
利用方法
npm i @co-labo-hub/fetcha
import { fetcha, FetchaError } from '@co-labo-hub/fetcha';
他
bodyの渡し方
- Content-Type が application/json で始まっている場合、
かつ body が objectの場合、JSON.stringify が実行されます
fetcha('https://example.com/api')
.contentType('application/json')
.post({name: 'foo'})
- body が Blob、FormData、URLSearchParams だった場合、Content-Type がクリアされます
参考:https://zenn.dev/kariya_mitsuru/articles/25c9aeb27059e7
const form = new URLSearchParams();
form.set("name", "foo");
fetcha('https://example.com/api')
.contentType('application/json') // 一致しないため無視される
.post(form)
ヘッダの指定方法
Content-Type は contentType メソッドで設定できますが、引数は空文字列か application/json の2択です。
参考:https://m0rter.anyfrog.net/2019/56/
空文字列の場合はヘッダから Content-Type を削除します。
他の Content-Type を設定する場合は header メソッドが使えます。
fetcha('https://example.com/api')
.header('Content-Type', 'text/plain')
メソッドの指定方法
fetch実行は下記メソッドが利用できます。
{method: string} でのタイプミスが避けられます。
参考:https://www.ohitori.fun/entry/how-to-fix-a-bug-in-the-fetch_api-patch-request
.get()
.head()
.delete()
.post(body?)
.patch(body?)
.put(body?)
//または
.fetch(method: "GET" | "POST" | "PATCH" | "PUT" | "HEAD" | "DELETE" = "GET")
JSON返値の型指定
// 標準のresp.json()の場合
const data = await fetcha('https://example.com/api')
.get()
.then(resp => resp.json() as Promise<{id: number}>)
// resp.toJson<T>()の場合
const data = await fetcha('https://example.com/api')
.get()
.then(resp => resp.toJson<{id: number}>());
URLの指定方法
柔軟に対応可能
//1
fetcha('https://example.com/api')
//2
fetcha().url('https://example.com/api')
//3
fetcha(new URL('/api', 'https://example.com/'))
//4
fetcha('/api')
.origin('https://example.com/')
//5
fetcha()
.origin('https://example.com/')
.url('/api')
エラー処理
エラーオブジェクトにレスポンスの各種プロパティが同名で含まれており
HTTPステータスコードを見て処理の振り分けなどが可能
.post()
.then(/* ... */)
.catch((e: FetchaError) => {
switch (e.status) {
case 500:
location.href = "/500.html";
return;
case 404:
location.href = "/404.html";
return;
case 401:
location.href = "/login.html";
return;
default:
alert(e.statusText);
}
})
詳細
サンプル
https://github.com/co-labo-hub/fetcha/blob/main/src/example.ts
最後に
fetchは実行前の組み立てが面倒ですが
エディタ上でメソッドの候補が表示され
選択していくことでメソッドチェーンが組み上がるのは気持ちいいです。
また、fetchは実行後のエラー処理が汚くなりがちですが、
catch内で必要な情報が揃った状態で処理が書けるので
クリーンなコードになるように思います。