Reputation: 43
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"?
(prn (:body response))
prints "false" but still returns theManyToManyChannel
(:body response)
surprisingly returns the same instead of "false".How can I proceed?
Upvotes: 2
Views: 1276
Reputation: 21926
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.
Upvotes: 1
Reputation: 4356
You cannot access the result of an async
operation (eg. go
) in a sync fashion. So the only way to get the actual response is in the async callback.
Getting the result in the REPL is a little tricky. You can store it in an atom and access it from the atom once the operation completes.
(def result-ref (atom nil))
(defn into-ref [chan]
(go (reset! result-ref (<! chan))))
(into-ref
(http/get "http://localhost:3000"
{:query-params
{"str1" str1
"str2" str2}}))
@result-ref
Of course you can only access the result once the operation has actually completed. The REPL is a bit tricky for async operations but this trick might help.
Upvotes: 2