re-frame-http-fx における on-success の範囲のメモ
補足
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 じゃないレスポンスを受け取ったりとか。
-
だから
reg-event-fx
の return に:http-xhrio
指定できるようになるのか。こういう「単に require するだけよくて参照しない」使い方、個人的には好きじゃない。何かしら参照しないと require するの忘れがち。 ↩︎
Discussion