0

I'm creating seed data for my database. The seed function is co-wrapped generator (https://www.npmjs.com/package/co):

createSeedData () {
  co(function * () {
     [...]
  }
}

At one point I'm trying to create 40 auctions with one bid each. Up until now I had a for-loop like this:

for (let i = 0; i <= 40; i++) {
  let auction = yield auction.create({
     [...]
  })  // Async creation of model and persisting it in db 
  yield bid.create({
    auction: auction.id
    [...]
  })
}

Now I'd like to create the auction in parallel but I can't quite get it to work.

co supports parallel execution when yield is used with arrays.

However I still need to create first an invoice, then a bid for it using yield.

I tried wrapping the above in a Promise and an inner co-wrapped generator function but it just never finishes execution.

How can I solve this problem? (If possible without using more packages)

Here is my attempt with the inner generator:

let promises = []
for (let i = 0; i <= 40; i++) {
  promises.push(new Promise(
    co(function *(resolve, reject) {
      let auction = yield auction.create({
        [...]
      })  // Async creation of model and persisting it in db

      yield bid.create({
        auction: auction.id
        [...]
      })
    )
    resolve()
  ))
}
yield invoicePromises
Hedge
  • 16,142
  • 42
  • 141
  • 246
  • Promises to the rescue, indeed! Please show us your attempt with the inner generator. Also, what does `create` return, is it using promises already? – Bergi Sep 19 '16 at 11:53
  • @Bergi `create` returns a Promise. I added the inner generator. – Hedge Sep 19 '16 at 15:23

1 Answers1

1

There's no need to call new Promise (and it doesn't work because you never call resolve or reject). Just omit that part, co() already returns a promise:

let promises = [];
for (let i = 0; i <= 40; i++) {
  promises.push( co(function *() {
    let auction = yield auction.create({
      [...]
    });  // Async creation of model and persisting it in db
    yield bid.create({
      auction: auction.id
      [...]
    });
  ));
}
yield invoicePromises;

If you don't want to use an inner generator, you can do the chaining with plain promises as well:

let promises = [];
for (let i = 0; i <= 40; i++) {
  promises.push(
    auction.create({
      [...]
    }).then(auction =>
      bid.create({
        auction: auction.id
        [...]
      });
    )
  );
}
yield Promise.all(invoicePromises);
Bergi
  • 630,263
  • 148
  • 957
  • 1,375
  • Awesome this works. I've had a `resolve()` in my code before but without adding a Promise explicitely it is even better. – Hedge Sep 19 '16 at 17:27
  • Yes, introducing it unnecessarily even is an [antipattern](http://stackoverflow.com/q/23803743/1048572) - you would have needed to use `try{…}catch(e){reject(e)}` in the generator as well to propagate errors – Bergi Sep 19 '16 at 17:35