0
votes

I'm facing an issue while using bluebird Promises. I'm using CoffeeScript but JavaScript answers are welcome too :)

Here is what I'm trying to do :

Code example

Promise = require 'bluebird'
Model = Promise.promisifyAll(require '[...]') # mongoose model promisified

getOpts = () -> [...] # whatever

Promise.each [1..3], (number) ->
  opts = getOpts(number)
  return Model.count(opts).exec (err, count) ->
    return "the count is #{count}"
.spread () ->
  console.log JSON.stringify arguments
  result = arguments.join(',')
  [...]

Explanations

I want to run the same function with 1, 2, 3 (sequentially), so I use bluebird's .each function. In the function, I need to get a count from my database. I'm using mongoose with bluebird's promisifyAll function to return a Promise and make sure that .each waits until each query is done to go next.

Then, I would like to gather the result of each query. I'm using bluebird's spread to gather the return values of .each. However, it doesn't contain the return value of the nested promise. arguments value is :

{
  "0": 1,
  "1": 2,
  "2": 3
}

Any ideas ?

Thanks

EDIT

Looks like bluebird's .each doesn't go well with .spread. I'm investigating on this issue.

EDIT 2

(Thanks Bergi)

I found a solution : first I build an array of functions. Then I call bluebird's .all on this array, and then .spread.

EDIT 3

Ok, I finally tried .map instead of .each and it works great also.

1

1 Answers

2
votes

Looks like bluebird's .each doesn't go well with .spread

Yes indeed. each does return a promise for an array, if you want to use that array just use then:

Promise.each [1..3], (number) ->
  opts = getOpts(number)
  Model.countAsync(opts).then (count) ->
    "the count is #{count}"
.then (args) ->
  console.log JSON.stringify args
  result = args.join(',')
  […]

spread is only for callback functions that want to use an individual variable (function parameter) for every array element, like .spread (firstResult, secondResult, thirdResult) -> ….

Also, arguments is an array-like object, not a true array, that's why you get that odd JSON representation and why the .join call does throw an exception.

However, it doesn't contain the return value of the nested promise

Yes, each was thought for side effects only originally, and instead of collecting results it returns the original input. This will change with version 3.0. Until then, you can use map. See Bluebird: getting the results of each() for further details.