0

I am using Sequelize, which uses Bluebird promises and need to iterate over an array of objects (inserting them one by one - bulkCreate cannot handle duplicate checks on mssql).

It looks something like this:

var users = [.....] // Filled up somewhere else.

Product.create(model)
  .then(function() {
      return users;
  })
  .each(function(user) {
      return User.create(......);
  })

My question is: Is it ok to return an array of stuff (not promises) like I do in the then?

EDIT: Another example

Here is another, better, example of that I was trying to do (with the exception of that this is a setTimeout() instead of a database write). And it looks like it works. It takes each element in the array (two, three, four) and executes the function send to each().

var Promise = require("bluebird");
function myDelay(who) {
    var deferred = Promise.pending();

    console.log("Starting: " + who);

    setTimeout(function() {
        console.log("Done with: " + who);
        deferred.resolve();         
    }, 250);

    return deferred.promise;
}

myDelay("one")
    .then(function() {
        return ["two", "three", "four"];
    })
    .each(function(who) {
        return myDelay(who);
    })
    .then(function() {
        console.log("All done!");
    });

It looks to me like it works fine. The output looks like this:

Starting: one
Done with: one
Starting: two
Done with: two
Starting: three
Done with: three
Starting: four
Done with: four
All done!

with a small delay between each "number".

Sten
  • 1,079
  • 11
  • 25
  • What are you trying to achieve - that code looks like it wont work - does it do anything? – Jaromanda X Sep 09 '15 at 09:49
  • It is pseudocode (kind of)... I want to execute one database insert call per item in the array. – Sten Sep 09 '15 at 09:50
  • If you return a value, that is not a Promise from a `then()`, this value will be wrapped with a Promise. So your code wont work in the way, you intent to. – Sirko Sep 09 '15 at 09:52
  • no wonder it looks broken - look at the accepted answer here http://stackoverflow.com/questions/24586110/resolve-promises-one-after-another-i-e-in-sequence - there's a paragraph on how to do what you want (I think) in bluebird – Jaromanda X Sep 09 '15 at 09:55
  • @Sirko - read the comment above yours - it's pseudocode :p – Jaromanda X Sep 09 '15 at 09:56
  • You're confusing the value returned by `.then`, which is a promise, with the value with which the promise is fulfilled, which is passed as a parameter to `.then` handlers. –  Sep 09 '15 at 10:36
  • I just added another example in the question that better illustrates what I was trying to achieve. And it looks like it works. But your comments leads me to believe I am still missing something. Or is the each() working differently in bluebird than in other promise libraries? – Sten Sep 09 '15 at 12:02
  • if that's what you want, then it's good. – RadleyMith Sep 09 '15 at 12:07

1 Answers1

1

Is it ok to return an array of stuff (not promises) from a then callback?

Yes, this is totally fine. The returned promise will then resolve with that callback return value directly, not with the result of some promise. then does automatically distinguish promises from non-promises as a part of its assimilation procedure. Your returned users array here is no different in that regard from the undefined that your last (logging) callback returns.

Your second example is totally fine, only in your first example I'm a bit concerned about the "filled up somewhere else" - you should keep that as local as possible. The users don't really seem to depend on the result of the Product.create(model) promise, so it's a bit odd to have them put in that callback there.

Bergi
  • 630,263
  • 148
  • 957
  • 1,375