I've got a setInterval
that runs a promise every second, inside the then function of every promise, I put the output into a MongoDB database (although for some reason it's not working).
I want to close the connection to the database when everything is done, but I don't know how to to make the closing of the connection only run when all promises are done and everything has finished writing to the DB.
Here is my current code:
I've got a client.js
file, meant to issue the query to a shop, using a promise, and a db.js
, meant to handle DB functionality.
client.js
var id = setInterval(function(){
if (i == (categories.length-1))
clearInterval(id);
var category = categories[i];
client.itemSearch({
searchIndex: SearchIndex,
categoryID: category.id,
keywords: currentKeyword
})
.then(function(results){
var title = results[0].Title;
var cat = category.name;
var price = results[0].Price
db.insertProduct(title,cat,price).then(function(){
console.log("Added " + title);
})
},function(err) {
console.log("error at " + category.name);
});
i+=1;
}, 1000)
queryStore();
db.js
var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost:27017/catalog');
var schema = new mongoose.Schema({
title : String,
category : String,
price : Number,
}, {collection: "catalog"});
var Product = mongoose.model("Product", schema);
Product.remove({}, function() {
console.log('Database cleared.')
});
exports.clearDB = function() {
Product.remove({});
}
exports.insertProduct = function (Title,Category,Price) {
var entry = new Product({
title: Title,
category: Category,
price: Price,
});
entry.save();
}
exports.closeConn = function() {
console.log("Closing DB Connection");
mongoose.connect().close();
}
Also, since I'm absolutely new to JavaScript and Node.js in general, any best practices or general tips will be greatly appreciated! :)
I've got a setInterval
that runs a promise every second, inside the then function of every promise, I put the output into a MongoDB database (although for some reason it's not working).
I want to close the connection to the database when everything is done, but I don't know how to to make the closing of the connection only run when all promises are done and everything has finished writing to the DB.
Here is my current code:
I've got a client.js
file, meant to issue the query to a shop, using a promise, and a db.js
, meant to handle DB functionality.
client.js
var id = setInterval(function(){
if (i == (categories.length-1))
clearInterval(id);
var category = categories[i];
client.itemSearch({
searchIndex: SearchIndex,
categoryID: category.id,
keywords: currentKeyword
})
.then(function(results){
var title = results[0].Title;
var cat = category.name;
var price = results[0].Price
db.insertProduct(title,cat,price).then(function(){
console.log("Added " + title);
})
},function(err) {
console.log("error at " + category.name);
});
i+=1;
}, 1000)
queryStore();
db.js
var mongoose = require("mongoose");
mongoose.connect('mongodb://localhost:27017/catalog');
var schema = new mongoose.Schema({
title : String,
category : String,
price : Number,
}, {collection: "catalog"});
var Product = mongoose.model("Product", schema);
Product.remove({}, function() {
console.log('Database cleared.')
});
exports.clearDB = function() {
Product.remove({});
}
exports.insertProduct = function (Title,Category,Price) {
var entry = new Product({
title: Title,
category: Category,
price: Price,
});
entry.save();
}
exports.closeConn = function() {
console.log("Closing DB Connection");
mongoose.connect().close();
}
Also, since I'm absolutely new to JavaScript and Node.js in general, any best practices or general tips will be greatly appreciated! :)
Share Improve this question edited Jan 12, 2016 at 22:52 J0e3gan 8,95810 gold badges57 silver badges81 bronze badges asked Jan 12, 2016 at 22:14 DaedalusDaedalus 3051 gold badge6 silver badges15 bronze badges 4- 1 Promises are not "run", they only are created. – Bergi Commented Jan 12, 2016 at 22:22
-
1
I really remend not to use
setInterval
together with promises. PromisifysetTimeout
and only use that. – Bergi Commented Jan 12, 2016 at 22:22 - @Bergi could you elaborate? I'm not sure I understand what that means – Daedalus Commented Jan 12, 2016 at 22:24
- If you refer to my first ment, it's just about terminology. Promises are values, not something that can be executed. – Bergi Commented Jan 12, 2016 at 22:27
1 Answer
Reset to default 4As written you are relying on a 1 second interval to impose a delay between successive calls of a search/insert sequence. There's nothing fundamentally wrong with that but it doesn't guarantee that each step is plete before the next one starts, and doesn't guarantee that the next step starts as soon as possible. At each step, the 1 second delay may be more than adequate or less than adequate, you don't really know.
Fortunately, promises offer a much better way to cope with the asynchronism.
Starting with an array, a well tried reduce
pattern is available (see "The Collection Kerfuffle" here to impose a sequence :
array.reduce(function(promise, item) {
return promise.then(function() {
return doSomethingAsync(item);
});
}, Promise.resolve());
where Promise
is ES6's native Promise, or eg Bluebird.
For the code in the question, the doSomethingAsync()
part expands to give :
categories.reduce(function(promise, category) {
return promise.then(function() {
return client.itemSearch({
'searchIndex': SearchIndex,
'categoryID': category.id,
'keywords': currentKeyword
}).then(function(results) {
var title = results[0].Title;
var cat = category.name;
var price = results[0].Price;
return db.insertProduct(title, cat, price);
}).then(function() {
console.log("Added " + title);
}).catch(function(err) {
console.log("error at " + category.name);
});
});
}, Promise.resolve());
The entire reduction process returns a promise, which can itself be returned and/or aggregated with other promises.