🎸

ポストaxiosのky

2020/10/03に公開

kyとは

kyはブラウザとDenoのためのhttp clientです。
最近ではNuxt.jsのhttp moduleに使用されるなど、人気が高まりつつあります。
名前の由来は特にないみたいだが、日本語のKYも意識されているみたい?

A form of text-able slang, KY is an abbreviation for 空気読めない (kuuki yomenai),  
which literally translates into “cannot read the air.”   
It's a phrase applied to someone who misses the implied meaning.

axiosとの違い

  • axiosはXMLHttpRequestで実装されているのに対し、kyはfetchで実装されているので、Service Workerに対応可能
  • axiosはfetchにある機能も独自に実装しているので、より安定しているfetch apiをベースにしているkyの方がバグが少ない(本人談)
  • 軽量(axiosは4.6KB、kyは2.8KB)
  • リクエストのリトライ機能がある。
    特にaxiosと比べて欠点はなさそう。

使い方

GET

import ky from 'ky';

(async () => {
  const res = await ky.get('https://reqres.in/api/users/1').json();
})();

POST

import ky from 'ky';

(async () => {
    const res = await ky
        .post('https://reqres.in/api/users/', {
            json: {
                name: 'Luke Skywalker',
                job: 'Jedi',
            },
        })
        .json();
})();

第一引数にリクエストのurl、第二引数にoptionのオブジェクトを渡します。
optionはfetchと同じ項目に加えて、いくつか独自の項目があります。

json

jsonを送信するときはbodyの代わりに、このjsonオプションにオブジェクトを設定できる。上のPOSTの例でも使いました。

searchParams

クエリパラメーターの設定

import ky from 'ky';

(async () => {
  const res = await ky
      .get('https://reqres.in/api/users/', {
          searchParams: {
            page: 2
          },
      })
      // /api/users?page=2
      .json();
})();

prefixUrl

リクエストurlのprefixを指定します。prefixの文字列の最後に/を付けなくても自動的に追加されます。

import ky from "ky";

(async () => {
    const res = await ky
        .post('users', {
            prefixUrl: 'https://reqres.in/api',
            json: {
                name: 'Luke Skywalker',
                job: 'Jedi',
            },
        })
	// https://reqres.in/api/users
        .json();
})();

retry

リクエストが失敗した際にリトライする設定。

  • limit: リトライできる最大回数
  • methods: http methodの配列
  • statusCodes: リトライを行うhttp statusの配列
  • maxRetryAfter: Retry-Afterの上限を設定。

単に数値を設定した場合はlimitの値が設定される。

import ky from "ky";

(async () => {
  const res = await ky
    .post('https://reqres.in/api/login', {
      retry: 10
    })
    .json();
})();

(async () => {
  const res = await ky
    .post('https://reqres.in/api/login', {
      retry: {
        limit: 10,
        methods: ['post'],
        statusCodes: [503],
      },
    })
    .json();
})();

timeout

defaultでは10000ms。
falseにするとtimeoutなしにもできる。

hooks

リクエストのライフサイクルで実行する関数を配列で設定する。ライフサイクル一覧とそれぞれの関数の型を以下の通り。

  • beforeRequests リクエストを送信する前
beforeRequests: BeforeRequestHook[]
export type BeforeRequestHook = (
	request: Request,
	options: NormalizedOptions,
) => Request | Response | void | Promise<Request | Response | void>;
  • beforeRetry リトライする前
    公式の例にもあるが、リトライ前にapi tokenをリフレッシュするときに便利そう。
beforeRetry: BeforeRetryHook[]
export type BeforeRetryHook = (options: {
	request: Request;
	response: Response;
	options: NormalizedOptions;
	error: Error;
	retryCount: number;
}) => void | Promise<void>;
  • afterResponse レスポンスを受け取った後
    レスポンスのstatusによって、その後の処理を変えたいなど
afterResponse: AfterResponseHook[]
export type AfterResponseHook = (
	request: Request,
	options: NormalizedOptions,
	response: Response,
) => Response | void | Promise<Response | void>;

onDownloadProgress

ダウンロードの進捗状況を取得できる。

onDownloadProgress: (progress: DownloadProgress, chunk: Uint8Array) => void;

interface DownloadProgress {
	percent: number;
	transferredBytes: number;
	totalBytes: number;
}

例えば、Reactでプログレスバーを表示するときはこんな感じ。

import React, {FC, useEffect, useState} from 'react';
import ky from 'ky';
import {Progress} from 'semantic-ui-react';

const Home: FC = () => {
  const [percent, setPercent] = useState<number>(0);
  useEffect(() => {
    const fetch = async () => {
      await ky(
        'https://fetch-progress.anthum.com/30kbps/images/sunrise-baseline.jpg',
        {
          onDownloadProgress: (progress, _) => {
            setPercent(progress.percent * 100);
          },
        },
      );
    };
    fetch();
  }, []);
  return (
    <>
      <h1>{Math.floor(percent)}%</h1>
      <div>
        <Progress percent={percent} color="orange" />
      </div>
    </>
  );
};

export default Home;

よく使うoptionはこんな感じかなと思います。

最後に

新規のプロジェクトはaxiosではなく、kyの採用をご検討ください。

参照

sampleで使用したapiやダウンロード画像は以下の物を使用しました。

Discussion