Anthony Kong Anthony Kong - 2 months ago 12
CoffeeScript Question

How to make _.each handle both 'array' and 'array of array' in $.when done handler

I have to perform a number of json calls and apply callback to the result. The number of call is unknown until runtime. Therefore I use

$.when.apply
to pass an array of promise to
when
.

jsonPromises = []
newContentActions = []
for model in models
jsonPromises.push contentCreator.create(model)
action = new ActionHandler model
newContentActions.push action

$.when.apply($, jsonPromises)
.then (args...) =>
_.each args, (result, idx) =>
return unless result[1] is 'success'
action = newContentActions[idx]
action result[0]


It works as expected, more or less. When there is more than 1 promise, the
then
handler of
$.when
will get an array of array (e.g.
[[Object, "success", Object], [Object, "success", Object]]
as seen in Chrome dev console).
_.each
can then correctly unpack it into
result, idx
.

However if there is only 1 promise, I will only get a single array in the
then
handler. It confuses
_.each
.
each
unpacks the single array and results into 3 function calls. And my app fails.

To get around this I make an extra check on the number of promise. When there is only one I will not use
$.when
:

if jsonPromises.length is 1
jsonPromises[0].done (model) =>
action = newContentActions[0]
action model
else
$.when.apply($, jsonPromises)
.then (args...) =>
_.each args, (result, idx) =>
return unless result[1] is 'success'
action = newContentActions[idx]
action result[0]


Is it the only way to achieve this result? Is there a way to remove the
jsonPromises.length is 1
check?

Answer

My solution would be to just wrap the args in an array if you see that jsonPromises.length is 1

  $.when.apply($, jsonPromises)
  .then (args...) =>
    args = [args] if jsonPromises.length is 1
    _.each args, (result, idx) =>
    return unless result[1] is 'success'
    action = newContentActions[idx]
    action result[0]