21

I'm trying to run 2 promises in paralel with sequelize, and then render the results in a .ejs template, but I'm receiving this error:

 Promise.all(...).spread is not a function

This is my code:

var environment_hash = req.session.passport.user.environment_hash;
var Template  = require('../models/index').Template;
var List      = require('../models/index').List;

var values = { 
    where: { environment_hash: environment_hash,
             is_deleted: 0 
        }                    
};

template = Template.findAll(values);
list = List.findAll(values);


Promise.all([template,list]).spread(function(templates,lists) {

    res.render('campaign/create.ejs', {
        templates: templates,
        lists: lists
    });

});

How can I solve thhis?

Filipe Ferminiano
  • 8,373
  • 25
  • 104
  • 174
  • 5
    `.spread()` is not a standard promise method. It is available in the Bluebird promise library - are you using that? Your code you included does not show that. You can also just use `.then(results => {...})` and access the results as `results[0]` and `results[1]`. – jfriend00 Mar 12 '17 at 16:56
  • Thanks, I didn't know that. I imported BlueBird and it's working now. – Filipe Ferminiano Mar 12 '17 at 16:59
  • **`"I'm trying to run 2 promises in parallel".`** No you are not because you cannot as JS is single threaded. What you are dealing with is that you don't know which promise will end first. – bugwheels94 Mar 12 '17 at 17:09
  • 1
    @ankitbug94, but it still can be parallel IO operations. – vp_arth Mar 12 '17 at 17:10
  • @vp_arth so what? promises are neither going to start at same time nor end at same time and OP mentioned **promise** – bugwheels94 Mar 12 '17 at 17:11
  • 1
    Based on my prior comment, I posted an answer that offers you three different solutions. The most elegant of which is to use destructing to remove the need for `.spread()` entirely, though I still recommend Bluebird for these reasons: [Are there still reasons to use promise libraries like Q or BlueBird now that we have ES6 promises?](http://stackoverflow.com/questions/34960886/are-there-still-reasons-to-use-promise-libraries-like-q-or-bluebird-now-that-we/34961040#34961040) – jfriend00 Mar 12 '17 at 17:11

4 Answers4

48

I'll make my comment into an answer since it solved your issue.

.spread() is not a standard promise method. It is available in the Bluebird promise library. Your code you included does not show that. Three possible solutions:

Access array values directly

You can just use .then(results => {...}) and access the results as results[0] and results[1].

Include the Bluebird Promise library

You can include the Bluebird promise library so you have access to .spread().

var Promise = require('bluebird');

Use destructuring in the callback arguments

In the latest versions of nodejs, you could also use destructuring assignment which kind of removes the need for .spread() like this:

Promise.all([template,list]).then(function([templates,lists]) {
    res.render('campaign/create.ejs', {templates, lists});
});
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • +1 [destructuring](http://2ality.com/2015/01/es6-destructuring.html) assignment , or maybe better to call it "destructuring to parameters" – Nate Anderson Apr 29 '18 at 18:44
20

You can write it without non-standard Bluebird features and keep less dependencies as well.

Promise.all([template,list])
  .then(function([templates,lists]) {
  };

ES6 Destructuring assignment

Promise.all([
  Promise.resolve(1),
  Promise.resolve(2),
]).then(([one, two]) => console.log(one, two));
vp_arth
  • 14,461
  • 4
  • 37
  • 66
1

This is a Bluebird Promise feature and you can access it via Sequelize.Promise without installing Bluebird module itself

Sequelize.Promise.all(promises).spread(...)
piotrbienias
  • 7,201
  • 1
  • 28
  • 33
0

I needed to install BlueBird.

npm install bluebird

Then:

var Promise = require("bluebird");
Filipe Ferminiano
  • 8,373
  • 25
  • 104
  • 174