0

I know I'm going to post this and then get it working, not to mention the title but...

I'm in a situation where I need to do some async code to each element in an array that I'm given, and then do some checks after all of them have finished. Normally, if I would use async.js here, however the way I'm doing it isn't getting my the results I want.

So this is my logic, I figure I can create an array of functions, however the way I'm doing this seems to have async.js returning me a list of functions in the result.

findLeadThatCanBeTaken : (leads, user, manualTake, cb) =>
  if(leads.length == 0) then return cb(null, null)

  funcArr = []
  self = this

  for lead in leads
    fun = (callback) ->
      console.log(lead.state)
      State.get lead.state, (e, state) ->
        if !state or state.canBeCalled(self.currentTime())
          return callback(null, lead._id.toString)

        return callback(null, null)

    funcArr.push(fun)

  async.parallel funcArr, (e, r) ->
    if (e)
      return cb(message:'No leads can be called at the current time', null)

    id = _.compact(r)
    id = r[0] if r.length

    if (!id || !id.length)
      return cb(message:'No leads can be called at the current time', null)

    lead = _.filter leads, (l) -> return l._id.toString() == id

    # Code handling 
    @takeLead(lead, user, cb)

I'm 90% sure the issue is this array I am creating isn't being assigned like I think it is, but I'm not sure. Anyone know what I'm doing wrong here?

1 Answer 1

2

I'd guess that you have a classic "closure inside a loop" problem:

for lead in leads
  fun = (callback) ->
    # some stuff that uses 'lead'...

The problem is that all your fun functions will have a reference to exactly the same lead and when those functions execute, lead will refer to the last value it had in the loop.

From the fine manual (bottom of that section):

When using a JavaScript loop to generate functions, it's common to insert a closure wrapper in order to ensure that loop variables are closed over, and all the generated functions don't just share the final values. CoffeeScript provides the do keyword, which immediately invokes a passed function, forwarding any arguments.

Sound familiar? You probably want to get the value of lead on each iteration rather than just dragging around lead itself with something like this:

for lead in leads
  do (lead) ->
    fun = (callback) ->
      # What you have now...
Sign up to request clarification or add additional context in comments.

1 Comment

Sorry for taking so long, I was playing with using do() but it wasn't working. Ends up, it was how I was pushing the function to that array, I was using something different than above at the time. Ends up this was the issue!

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.