useranon
useranon

Reputation: 29514

For loop in coffeescript

I am working on rails3.2 and using coffeescript

In my coffeescript i have a for loop and for each , i am executing a API call to fetch results and appending the results to the respective dom

like

for ajaxLink in _ajaxRenderLinks
      _template = $(ajaxLink).attr('data-link-template')
      apiURL = $(ajaxLink).attr('data-link-url')
      console.log($(ajaxLink))
      Myapp.API.execute(apiURL, 'get', {}, (data) ->
        console.log($(ajaxLink))
        if data isnt "" or data isnt undefined
          console.log($(ajaxLink))
          $(ajaxLink).empty()
          $(ajaxLink).append($(HandlebarsTemplates[Myapp.TemplateRoutes.path(_template)](data))))

In the above code, i have two links (one is a link and another is a ul link) ajaxRenderLinks has these a and ul which has its template to render and the url to fetch the results. The first console.log prints the first link a and then runs the API call for it and then runs the APi call for it and then it prints the second link ul and runs the API CALl for it . And finally it tries to append the last result with the second link and not doing the appending for each link, since it ajaxLink inside if data isnt "" or data isnt undefined prints only the second link and not prints the first link and then second link

How to resolve this

Upvotes: 1

Views: 364

Answers (1)

Flambino
Flambino

Reputation: 18773

Looks like a classic "variable closure in a loop" situation. Because the execute function is asynchronous, it references ajaxLink, which changes as the loop loops. So when execute's callback is invoked, ajaxLink might be something else than what it was when execute itself was invoked.

Try this

for ajaxLink in _ajaxRenderLinks
  do (ajaxLink) ->         # wrap in an immediately-invoked function
    ajaxLink = $(ajaxLink) # save this rather than calling $(...) again and again
    _template = ajaxLink.attr('data-link-template')
    apiURL = ajaxLink.attr('data-link-url')
    Myapp.API.execute(apiURL, 'get', {}, (data) ->
      if data? and data isnt ""
        ajaxLink.empty().append($(HandlebarsTemplates[Myapp.TemplateRoutes.path(_template)](data))))

Upvotes: 5

Related Questions