Search code examples
clojurescript

ClojureScript: How to access (not just print) the result of an HTTP GET request


I am trying to build a simple client-server system with Clojure (server) and ClojureScript (client).

The server side is OK (everything is green on the browser's console, no CORS problems, etc.); the response is plain text ("true" or "false"). On the client side I am using basically the function included in the official cljs-http website

(defn get-request [str1 str2]
(go (let [response (<! (http/get "http://localhost:3000"
                                 {:query-params {"str1" str1
                                                 "str2" str2}}))]
  (prn response))))

Running this function on the REPL indicates that everything is fine and something map-like comes out of the async channel

cljs.user=> (b/get-request "foo" "bar")
#object[cljs.core.async.impl.channels.ManyToManyChannel]         ;; the result
cljs.user=> {:status 200, :success true, :body "false", [...]}   ;; output of `prn`

My question is: How can I actually get the response's body ouf of that ManyToManyChannel "object"?

  • For the sake of testing, changing the function's last expression to (prn (:body response)) prints "false" but still returns theManyToManyChannel
  • Changing the function's last expression to just (:body response) surprisingly returns the same instead of "false".

How can I proceed?


Solution

  • It's Saturday morning and I'm feeling lazy so I didn't run this, but this should work:

    (defn get-request [str1 str2]
      (go (<! (http/get "http://localhost:3000"
                        {:query-params {"str1" str1
                                        "str2" str2}}))))
    
    
    (defn read-response [response-chan]
      (go (let [resp (<! response-chan)]
            (prn resp))))  ; <- the only place where you can "touch" resp!
    
    (read-response (get-request "a" "b"))
    

    The go block returns a channel that will receive the result you put into it in the request response (the returned form from the go block in your original).

    The read function takes a channel and just reads from it, the last form just calls the second function with the result of calling the first.

    Remember that channels are first-class constructs, you can pass them around, share them with multiple consumers, etc.