🔲

re-frame-http-fx における on-success の範囲のメモ

2023/11/07に公開

補足

re-frame は ClojureScript のウェブフレームワーク。 View に React / Reagent を使っている。

re-frame-http-fx は re-frame において非同期 http request をハンドルするために使えるユーティリティ。 cljs-ajax の薄いラッパーになっている。

cljs-ajax はシンプルな Ajax client で ClojureScript と Clojure の両方をサポートしている。 goog.net.XhrIo のラッパー。

知りたかったこと

re-frame で re-frame-http-fx を使うとこんな感じのコードになる。

(re-frame/reg-event-fx
  ::http-post
  (fn [_world [_ val]]
    {:http-xhrio {:method          :post
                  :uri             "https://httpbin.org/post"
                  :params          data
                  :timeout         5000
                  :format          (ajax/json-request-format)
                  :response-format (ajax/json-response-format {:keywords? true})
                  :on-success      [::success-post-result]
                  :on-failure      [::failure-post-result]}}))
  • リクエストが成功した場合に :on-success に指定した event ( = re-frame event )が実行される。
  • 同じくリクエストが失敗した場合に :on-failure に指定した event が実行される。

では、どういう場合に「リクエストが成功した」とみなされるのか?

ソースコード

ここで effect handler を(勝手に)登録している[1]https://github.com/day8/re-frame-http-fx/blob/master/src/day8/re_frame/http_fx.cljs#L98

(reg-fx :http-xhrio http-effect)

http-effect 関数はその引数の request 内容を request->xhrio-options 関数に渡して実行。

request->xhrio-options 関数は cljs-ajax を(呼び出すのかと思いきや) (new goog.net.XhrIo) して、直接 goog.net.XhrIo を呼び出している。 cljs-ajax は使ってなさそう?昔は使ってたのかな https://github.com/day8/re-frame-http-fx/blob/master/src/day8/re_frame/http_fx.cljs#L47-L48C13

  ; wrap events in cljs-ajax callback
  (let [api (new goog.net.XhrIo)]

で、 リクエストハンドラとして ajax-xhrio-handler 関数に on-success や on-failure のコールバックも渡しつつ、さっきの (new goog.net.XhrIo) のレスポンス(api)も渡している。

ajax-xhrio-handler 関数を見ると (new goog.net.XhrIo) のレスポンス(api) から success? というのを取り出していて、これが判定に使われている。

続いて cljs-ajax のソースコードのほうで success? を探すとすぐ見つかる。 https://github.com/JulianBirch/cljs-ajax/blob/359e83ca0cd628c22252ba861860cb921622a618/src/ajax/util.cljc#L31-L48

(def successful-response-codes-set
  "A set of successful response types derived from `goog.net.HttpStatus.isSuccess`."
  ;; Factoid: Closure considers some 2XX status codes to *not* be successful, namely
  ;; 205 Reset Content, 207 Multi Status & the unspecified 208+ range
  #{200    ;; Ok
    201    ;; Created
    202    ;; Accepted
    204    ;; No Content
    206    ;; Partial Content
    304    ;; Not Modified
    ;; See https://github.com/google/closure-library/blob/f999480c4005641d284b86d82d0d5d0f05f3ffc8/closure/goog/net/httpstatus.js#L89-L94
    1223}) ;; QUIRK_IE_NO_CONTENT

(defn success? 
  "Indicates whether an HTTP status code is considered successful."
  [status]
  (contains? successful-response-codes-set
             status))

これらのステータスコードが success と見なされる。

補足2

ステータスコードが上記に該当しても、例えばレスポンスのパースに失敗したりするとステータスコードに関係なく on-failure に行く。自分がやったのは :response-format を json-response-format に指定しながら、JSON じゃないレスポンスを受け取ったりとか。

脚注
  1. だから reg-event-fx の return に :http-xhrio 指定できるようになるのか。こういう「単に require するだけよくて参照しない」使い方、個人的には好きじゃない。何かしら参照しないと require するの忘れがち。 ↩︎

Discussion