Reputation: 925
I'm trying to wrap my head around promises trying to solve a scenario I find myself in a lot of times: seeding a MongoDB database. So I got the following script which I want to turn into a Promise, preferably using ES6, but would take a bluebird as an answer if that's the case.
This is what I got using setTimeout
to give time to the write operations before closing the database:
// Importing the connection to the `bookshelf` db.
var bookshelfConn = require('./database');
// Importing the Mongoose model we'll use to write to the db.
var Book = require('./models/Book');
// Importing the Data to populate the db.
var books = require('./dataset');
// When the connection is ready, do the music!
bookshelfConn.on('open', function () {
dropDb(seedDb, closeDb);
});
function dropDb (cb1, cb2) {
bookshelfConn.db.dropDatabase();
console.log('Database dropped!');
cb1(cb2);
}
function seedDb (cb) {
console.time('Seeding Time'); // Benchmarking the seed process.
// Warning! Slow IO operation.
books.forEach(function (book) {
new Book(book).save(function (err) {
if (err) console.log('Oopsie!', err);
});
console.log('Seeding:', book);
});
console.timeEnd('Seeding Time'); // Benchmarking the seed process.
cb();
}
function closeDb () {
setTimeout(function () {
bookshelfConn.close(function () {
console.log('Mongoose connection closed!');
});
}, 1000); // Delay closing connection to give enough time to seed!
}
Updated code to reflect zangw's answer:
// Importing the connection to the `bookshelf` db.
var bookshelfConn = require('./database');
// Importing the Mongoose model we'll use to write to the db.
var Book = require('./models/Book');
// Importing the Data to populate the db.
var books = require('./dataset');
// When the connection is ready, do the music!
bookshelfConn.on('open', function () {
// Here we'll keep an array of Promises
var booksOps = [];
// We drop the db as soon the connection is open
bookshelfConn.db.dropDatabase(function () {
console.log('Database dropped');
});
// Creating a Promise for each save operation
books.forEach(function (book) {
booksOps.push(saveBookAsync(book));
});
// Running all the promises sequentially, and THEN
// closing the database.
Promise.all(booksOps).then(function () {
bookshelfConn.close(function () {
console.log('Mongoose connection closed!');
});
});
// This function returns a Promise.
function saveBookAsync (book) {
return new Promise(function (resolve, reject) {
new Book(book).save(function (err) {
if (err) reject(err);
else resolve();
});
});
}
});
Upvotes: 1
Views: 713
Reputation: 48436
Please try to do it through new Promise
and Promise.all
new Promise
to create a new promise. The passed in function will receive functions resolve and reject as its arguments which can be called to seal the fate of the created promise.
Promise.all
is useful for when you want to wait for more than one promise to complete.
var bookOps = [];
books.forEach(function (book) {
bookOps.push(saveBookAsync(book));
});
Promise.all(bookOps).then(function() {
bookshelfConn.close(function () {
console.log('Mongoose connection closed!');
});
});
function saveBookAsync(book) {
return new Promise(function(resolve, reject) {
new Book(book).save(function(err) {
if (err)
reject(err);
else
resolve();
})
});
}
Upvotes: 1