reasonml
FetchAPI

bs-fetch使ってみた

MLたいして触ったことない(※これ書くときに初めて触った) & 本職サーバーサイド&インフラで、
WEBは2年前Angular書いて以降は追えてない程度マンですが、AdventCalender誘ってもらったので書いてみます。

ReasonでAPIリクエストする処理を書こうとして、XHRかFetchないか探してみたら
bs-fetchを見つけたので使ってみたのを雑に書きました。

導入

1日目の記事テンプレート落としてきて、Installationのnpm installとbsconfig追記だけなので割愛。

使い方

サンプルコードには↓が載っていた。ヘッダ指定とかこまいところどうするのかわからん・・・

let _ =
  Js.Promise.(
    Fetch.fetch("/api/hellos/1")
    |> then_(Fetch.Response.text)
    |> then_((text) => print_endline(text) |> resolve)
  );

Fetch.fetch系のシグニチャをみると、4通り実行方法が用意されている模様

external fetch : string -> response Js.Promise.t = "" [@@bs.val]
external fetchWithInit : string -> requestInit -> response Js.Promise.t = "fetch" [@@bs.val]
external fetchWithRequest : request -> response Js.Promise.t = "fetch" [@@bs.val]
external fetchWithRequestInit : request -> requestInit -> response Js.Promise.t = "fetch" [@@bs.val]
  • fetchは第一引数にurlのstringだけ渡してシンプルにGET
  • fetchWithInitは第一引数にurlのstring,第二引数にrequestInit型を渡して実行
  • fetchWithRequestは第一引数にrequest型を渡して実行
  • fetchWithRequestInitは第一引数にurlのrequest,第二引数にrequestInit型を渡して実行

Initは適用前、無印は適用後を表現しているのかな・・・?
ヘッダやbody指定してfetchするならfetchWithInitを使えば良さそう。

ドキュメントなさ気なのでソースサンプルから読み解く

HeaderInit

シグニチャ

  external make : < .. > Js.t -> t = "%identity"
  external makeWithArray : (string * string) array -> t = "%identity"

タプルのArray突っ込めば生成できる模様

Fetch.HeadersInit.makeWithArray([|("Accept-Encoding","gzip"), ("bar","foo")|])

RequestInit

シグニチャ↓

  let make
    ?method_:(method_: requestMethod option) 
    ?headers:(headers: headersInit option)
    ?body:(body: bodyInit option)
    ?referrer:(referrer: string option) 
    ?referrerPolicy:(referrerPolicy: referrerPolicy = None) 
    ?mode:(mode: requestMode option) 
    ?credentials:(credentials: requestCredentials option) 
    ?cache:(cache: requestCache option) 
    ?redirect:(redirect: requestRedirect option) 
    ?integrity:(integrity: string = "") 
    ?keepalive:(keepalive: bool option)
let requestInit = Fetch.RequestInit.make(
  ~method_=Post, 
  ~headers=Fetch.HeadersInit.makeWithArray([|("Accept-Encoding","gzip"), ("bar","foo")|]),
  ~mode=NoCORS, 
  () /* 指定していないoption型引数を埋める */
)

こまい設定できた。同じ要領でBodyInit使えばBody指定もできました。

実行

let _ =
  Js.Promise.(
    Fetch.fetchWithInit(
      "http://localhost:4000",
      Fetch.RequestInit.make(
        ~method_=Get,
        ~headers=Fetch.HeadersInit.makeWithArray([|("Accept-Encoding","gzip"), ("bar","foo")|]),
        ~mode=NoCORS,
      ())
    )
    |> then_((resp) => Fetch.Response.text(resp))
    |> then_((text) => print_endline(text) |> resolve)
    |> catch((e) => Js.log(e) |> resolve)
  );

直感的にかけて良い