39774

Code not called from go block, but it works from REPL

Question:

I have code that updates the DOM. new-recipe! calls an API to get a new recipe string. update-recipe-state next updates this state in the screen. Finally we have a call to update-transition-buttons.

(defn- add-listener-to-recipe-button! [] "Listens to go button, creates a new recipe and displays it" (create-click-event-listener! (dommy/sel1 :#button-start) #(go (new-recipe!) (<! (timeout 2000)) (update-recipe-state!) (<! (timeout 2000)) (update-transition-buttons! "onboarding")))) ;; define your app data so that it doesn't get over-written on reload (defonce world (add-listener-to-recipe-button!))

The update-transition-buttons has some delays between the steps (using the timeout code <a href="https://gist.github.com/swannodette/5882703" rel="nofollow">here</a>) looks as follows:

(defn- update-transition-buttons! [recipe-name] "Updates the buttons with the transition names" (go ;; Split response in list of actions by splitting on the comma (let [response (<! (http/get (get-recipe-transitions-url recipe-name))) transition-names (clojure.string/split (:body response) ",")] (go (update-buttons! transition-names) (<! (timeout 2000)) (js/console.log transition-names) (set-button-event-handlers! transition-names)))))

So it splits the response to a string. updates-buttons changes state on the page by adding some buttons (this is visible). Again there is a timeout, and then I want to <em>add the event handlers to the buttons</em>. This is where it goes wrong.

The routine to create event listeners (which also contain a console.log) look as follows:

(defn- listen-to-transition-button! [name] "Creates click event listener on button (button HTML ID should be name)" (do (js/console.log (str "Listening to " name)) (let [name-without-spaces (clojure.string/replace name " " "") button (dommy/sel1 (keyword (str "#" name-without-spaces))) action #(do (perform-action! name) (update-recipe-state!))] (create-click-event-listener! button action)))) (defn- set-button-event-handlers! [names] "Creates click event listeners on the buttons (button ID should be name)" (map listen-to-transition-button! names))

Again you see a console.log message that should happen for each elements that is passed. The output I get in the Firefox console is:

<blockquote>

[FIRST SERVICE CALLED]<br /> [NEXT SERVICE CALLED]<br /> [DISPLAY LIST OF STEPS]: ["Step1", "Step2", "Step3"]

</blockquote>

What I expect is:

<blockquote>

[FIRST SERVICE CALLED]<br /> [NEXT SERVICE CALLED]<br /> [DISPLAY LIST OF STEPS]: ["Step1", "Step2", "Step3"]<br /><strong>Listening to Step1<br /> Listening to Step2<br /> Listening to Step3</strong>

</blockquote>

So the event handlers (which depend on the HTML generated in the step before) are not added for some reason and the console.log message is not displayed.

When I call the <em>same code</em> from the REPL I do see the output, i.e.:

<blockquote>

repl=> (set-button-event-handlers! ["Step1","Step2", "Step3"])<br /> (#object[Object [object Object]] #object[Object [object Object]] #object[Object [object Object]])

</blockquote>

And the console output is:

<blockquote>

Listening to Step1<br /> Listening to Step2<br /> Listening to Step3

</blockquote>

Why can set-button-event-handlers! be called from the REPL, but not in the update-transition-buttons method after update-buttons?

Answer1:

looks like the problem is here:

(map listen-to-transition-button! names)

in set-button-event-handlers!

it creates a lazy seq, and elements won't be realized until their usage somewhere in code (which never happens), but when you call it in repl, it is being fully realized to show all the elements in output. Try changing this line to:

(doall (map listen-to-transition-button! names))

Recommend

  • high order bessel function computation with large variables
  • How to push data to variety of different client types in near real time?
  • ASP.NET: how to make onClientClick finish work before postback?
  • Install different versions of nuget packages inside one solution file with two projects
  • goJS dropdown remove items
  • Python: Split a String Field into 3 Separate Fields using Lambda
  • Manually Timing out a C# Thread
  • how can I compare dates in array to find the earliest one?
  • Watson Conversation - Why is the ANYTHING ELSE node not chosen
  • Divide a $1 by 3 and adjusting 1 cent
  • Swift Initialization Rule Confusion
  • How do I import an existing Grails 3 (3.0.12) project in IntelliJ 15
  • pickle.PicklingError: args[0] from __newobj__ args has the wrong class with hadoop python
  • Jenkins Grails plugin does not list lastest versions of Grails
  • Using $compile in a directive triggers AngularJS infinite digest error
  • KnockoutObservableArray with typed elements in TypeScript
  • How do I shift the decimal place in Python?
  • Checking if an array in C is symmetric
  • Sequential (transactional) API calls in angular 4 with state management
  • Access Android Market through SSH tunnel
  • C: Incompatible pointer type initializing
  • Installed module is empty
  • Make VS2015 use angular-cli ng at build time in a .NET project
  • Sencha Touch 2.0 Controller refs attribute not working?
  • When to use `image` and when to use `Matrix` in Emgu CV?
  • Update CALayer sublayers immediately
  • Is calc() supported in html email?
  • What is the “return” in scheme?
  • req.body is undefined - nodejs
  • Where to put my custom functions in Wordpress?
  • Which linear programming package should I use for high numbers of constraints and “warm starts” [clo
  • Symfony2: How to get request parameter
  • Akka Routing: Reply's send to router ends up as dead letters
  • Is there a mandatory requirement to switch app.yaml?
  • VB.net deserialize, JSON Conversion from type 'Dictionary(Of String,Object)' to type '
  • File upload with ng-file-upload throwing error
  • ExecuteAsync RestSharp to allow backgroundWorker CancellationPending c#
  • AngularJs get employee from factory
  • Why can't I rebase on to an ancestor of source changesets if on a different branch?
  • Unable to use reactive element in my shiny app