3

Context

I'm playing with ClojureScript, so Ajax works as follows for me:

(make-ajax-call url data handler);

where handler looks something like:

(fn [response] .... )

Now, this means when I want to say something like "fetch the new data, and update the left sidebar", my end ends up looking like:

(make-ajax-call "/fetch-new-data" {} update-sidebar!) [1]

Now, I'd prefer to write this as:

(update-sidebar! (make-ajax-call "/fetch-new-data" {})) [2]

but it won't work because make-ajax call returns immediately.

Question

Is there some way via monads, or macros, to make this work? So that [2] gets auto rewritten into [1] ? I believe:

  • there will be no performance penality, since it's rewritten into [1[
  • it's clearer for me to reason about since I can think in synchronous steps rather than async events

    I suspect I'm not the first to run into this problem, so if this is a well known problem, answers of the form "Google for Problem Foo" is perfectly valid.

Thanks!

2
  • Hi user1383359!, Have my answer (releated with core.async) helped you with this problem? I tried it and works very well Commented Oct 21, 2013 at 8:10
  • This post is specially related with core.async and doing ajax calls dimagog.github.io/blog/clojure/clojurescript/2013/07/12/… Commented Oct 22, 2013 at 15:51

4 Answers 4

2

Since Jun 28, 2013, the time that is released clojure core.async lib, you can do it, more or less, in this way: https://gist.github.com/juanantonioruz/7039755

Here the code pasted:

(ns fourclojure.stack
    (require [clojure.core.async :as async :refer :all]))

(defn update-sidebar! [new-data]
  (println "you have updated the sidebar with this data:" new-data))

(defn async-handler [the-channel data-recieved]
  (put! the-channel data-recieved)
  )

(defn make-ajax-call [url data-to-send]
  (let [the-channel (chan)]
    (go   
     (<! (timeout 2000)); wait 2 seconds to response
     (async-handler the-channel (str "return value with this url: " url)))
    the-channel
    )
  )

(update-sidebar! (<!! (make-ajax-call "/fetch-new-data" {})))

More info in:
* http://clojure.com/blog/2013/06/28/clojure-core-async-channels.html
* https://github.com/clojure/core.async/blob/master/examples/walkthrough.clj

Sign up to request clarification or add additional context in comments.

Comments

1

a macro would change the appearance of the code while leaving the Ajax call asynchronous. it's a simple template macro. another approach would be to wrap the call to make-ajax-call in a function that waits for the result. while either of these could be made to work they may seem a bit awkward and "un ajax like". will the benefits be worth the extra layer of abstraction?

Comments

1

What about using the threading macro? Isn't good enough?

(->> update-sidebar! (make-ajax-call "/fetch-new-data" {}))

Comments

1

We had rough ideas about this in the async branch of seesaw. See in particular the seesaw.async namespace.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.