Saving with mongoose to mongodb in a loop - node.js

I want to save an object multiple times, with a change to the date field - adding one month per iteration.
A for loop doesn't work due to node async nature.
const saveMany = (req, res, obj, data) => {
let saves = [];
if (data.frequency === 'monthly') {
let i = 0;
for (let i = 0; i < data.reccuring_length; i++) {
const newEntry = new obj(data);
if (i != 0) newEntry.created_date.addMonths(1) //using datejs
newEntry.save((err, entry) => {
if (err) {
return res.status(400).send({
message: err
});
}
saves.push(entry);
})
}) //end of for loop
return res.json(saves)
} //end of if
}
I've seen stuff about promises / the async library but can't make a working implementation (I am new to this though so could be missing something obvious).
Any help is appreciated :)
EDIT:
Saving To MongoDB In A Loop
Found this link which is relevant, but if anyone has other suggestions that would be great.
EDIT 2:
Just realised my code has camelcase and snake case, changing in my code to make all object data snake case.

I think you can do somethings like that:
const saveMany = async (req, res, obj, data) => {
let saves = [];
if (data.frequency === 'monthly') {
let i = 0;
for (let i = 0; i < data.reccuring_length; i++) {
const newEntry = new obj(data);
if (i != 0) newEntry.created_date.addMonths(1) //using datejs
try{
const entry= await newEntry.save();
saves.push(entry);
} catch(err) {
return res.status(400).send({ message: err });
}
}) //end of for loop
return res.json(saves)
} //end of if
}

Related

foreach loop in sync function in nodejs

I have code written
function getDetails (req, res) {
const dbQuery = `call spGetSLAReportsDetails('${req.body.domainId}', ${req.body.days},'${req.body.type}','${req.body.app}')`
try {
connectDatabase(dbQuery).then((rows) => {
if (!_.isEmpty(rows.dbData) && !_.isEmpty(rows.dbData[0])) {
const resultList = []
rows.dbData.pop()
var bar = new Promise((resolve, reject) => {
rows.dbData[0].forEach((element, index, array) => {
let query = `select * from YCW.YWFWIC ic where ic.witem=${element.witem} and ic.reqno=${element.reqno};`
connectDatabase(query).then((data) =>{
for (var i = 0; i < data.dbData.length; i++) {
element[data.dbData[i]["cfield"]] = data.dbData[i]["cvalue"]
}
resultList.push(element)
// console.log(resultList)
}).catch((err) => {
console.log(err)
})
if (index === array.length -1) resolve();
});
});
bar.then(() => {
console.log(resultList);
});
res.status(msgCodeJson.ERR004.code).send({
result: resultList })
} else {
console.log("empty array")
res.status(msgCodeJson.ERR004.code).send({
message : "No data found"
})
// httpResponseHandlerError(res, msgCodeJson.ERR001.code, msgCodeJson.ERR001.msg)
}
}).catch(() => {
httpResponseHandlerError(res, msgCodeJson.ERR002.code, msgCodeJson.ERR002.msg)
})
} catch (err) {
httpResponseHandlerError(res, msgCodeJson.ERR009.code, msgCodeJson.ERR009.msg)
}
}
module.exports.getDetails = getDetails
i want data to be fit in resultlist but i get empty list after all operation.
while in foreach loop i am getting proper output.
kindly help in issue.
i tried with async foreach loop but some syntax error is coming.
kindly help
as mentioned in the comment of the code you're using
Best way to wait for .forEach() to complete
This is OK if there is no async processing inside the loop.
yet you have an async function inside your forEach callback, namly this:
connectDatabase(query).then((data) => {
for (var i = 0; i < data.dbData.length; i++) {
element[data.dbData[i]["cfield"]] = data.dbData[i]["cvalue"]
}
resultList.push(element)
}).catch((err) => {
console.log(err)
})
you'll need to resolve the "outer/parent" promise from inside the "inner/child" promise
I suggest using a regular good old for loop and/or checking the count of resolved promises against the rows.dbData[0].length and calling a final code/function once they match

How to save each array to each document with 'for' in Nodejs with mongoose

I want to save each array data into each document at Nodejs.
Therefore I made this code below.
But when I run this code, it only saves body[0].
Could you recommend some solution?
exports.saveOrder = (req, res) => {
const body = JSON.parse(res);
for (let i = 0; i < body.length; i += 1) {
const eachBody = body[i];
const order = new Order(eachBody);
order.save();
return res.send('order is saved');
}
}
}
};
For Db operations, You need to use promise or async/await, and send response once after all orders saved to DB. Add try/catch to catch errors as well.
Check this code, it should work now.
exports.saveOrder = async (req, res) => {
try {
const body = JSON.parse(res); // check this before do you realy need to parse it or not
const allResults = [];
for (let i = 0; i < body.length; i += 1) {
const eachBody = body[i];
const order = new Order(eachBody);
const result = await order.save();
allResults.push(result);
}
return res.send(allResults);
} catch (e) {
console.log(e);
return res.send(e);
}
};
This is because you have send the response(used return) inside the for loop.
So it saves body[0] and return the response.
Use "return" outside the "for loop".
for (let i = 0; i < body.length; i += 1) {
const eachBody = body[i];
const order = new Order(eachBody);
order.save();
}
return res.send('order is saved');

Nodejs promise child resolve parent promise

I currently have two promises, whereas the child is dependent on the parents success. I want to Resolve/reject the parent promise from the child promises "then".
const UserApplicaiton = require('../applications/user'), User = new UserApplicaiton();
class CheckParams {
constructor() { }
required(params, required_params) {
return new Promise(function(resolve, reject, onCancel) {
// set i
var i;
// set missed_required_params
var missed_required_params = [];
// check for userCredentials if user_id is required param, convert from credentials to user_id
if(required_params.includes("user_id")){
// set as const
const user_key = String(params.userCredentials.user_key);
const user_secret = String(params.userCredentials.user_secret);
// check in database
User.info(user_key, user_secret).then((data) => {
// if data
if(data) {
// add user_id to params
params.user_id = data[0]._id;
// loop params
for(i = 0; i < required_params.length; i++){
// if params that's required is there, else add to array
if(!(required_params[i] in params)){
missed_required_params.push(required_params[i]);
}
}
if(missed_required_params.length !== 0){
reject("Missed parameters: " + missed_required_params);
}else{
resolve(params);
}
}
}).catch((err) => {
reject(err);
});
}else{
// loop params
for(i = 0; i < required_params.length; i++){
// if params that's required is there, else add to array
if(!(required_params[i] in params)){
missed_required_params.push(required_params[i]);
}
}
if(missed_required_params.length !== 0){
console.log("hello");
return reject("Missed parameters: " + missed_required_params);
}else{
console.log("hello2");
resolve(1);
}
}
});
}
}
module.exports = CheckParams;
The goal for the second promise is to add to an object based on the response, and then resolve the parent promise, which will be used later in the code.
This doesn't work at all. Async doesn't really help.
Your problem appears to be that if(data) { is missing an else clause where you would settle the promise as well. Avoiding the Promise constructor antipattern helps to avoid such mistakes as well.
required(params, required_params) {
var promise;
if (required_params.includes("user_id")) {
const user_key = String(params.userCredentials.user_key);
const user_secret = String(params.userCredentials.user_secret);
promise = User.info(user_key, user_secret).then((data) => {
if (data) {
params.user_id = data[0]._id;
}
// else
// throw error? keep user_id undefined?
})
} else {
promise = Promise.resolve();
}
return promise.then(() => {
var missed_required_params = [];
for (var i = 0; i < required_params.length; i++) {
if (!(required_params[i] in params)) {
missed_required_params.push(required_params[i]);
}
}
if (missed_required_params.length !== 0) {
throw new Error("Missed parameters: " + missed_required_params);
} else {
return params;
}
});
}

Node.js database result return late inside the function

Node.js database result return late inside the function
const db = req.app.db;
function getFeaturebyID(featureids) {
db.planFeatures.findOne({"_id": featureids }).then(features => {
return features.planFeaturesTitle;
});
}
const planLists ={};
db.planManagement.find({}).toArray((err, planList) => {
// res.end(JSON.stringify(planList));
featurearray = [];
var j =1;
planList.forEach(function(row) {
planLists._id = row._id;
features = row.planFeatures.split(',');
for (let i = 0; i < features.length; i++) {
featurearray[i] = getFeaturebyID(features[i]);
// console.log(getFeaturebyID(features[i]));
}
//row.planFeaturesName[j] = featurearray;
console.log(featurearray);
j++;
});
//console.log(planList);
// res.end(JSON.stringify(req.session));
res.render('stylist/plan_selection', {
top_results: planList,
title: 'Schedule',
config: req.app.config,
session: req.session,
message: common.clearSessionValue(req.session, 'message'),
messageType: common.clearSessionValue(req.session, 'messageType'),
helpers: req.handlebars.helpers,
showFooter: 'showFooter'
});
});
});
return features.planFeaturesTitle; return a value late while calling the function. I try callback but not works
This is due to asynchronous nature of node.js,
First declare your function async like this,
const getFeaturebyID = async (featureids) => {
const features = await db.planFeatures.findOne({"_id": featureids });
return features.planFeaturesTitle;
}
Then use it like this,
planList.forEach(async (row) => {
// your code here
for (let i = 0; i < features.length; i++) {
featurearray[i] = await getFeaturebyID(features[i]);
}
// your code here
});

How could I return an array from my module to my API using promise? Async Functions and Promise - Node.js

I need to return a json object to my api. To do this I have a module that does some requests and should return the results.
My problem is grasping the promise concept and implementing it.
server.js
app.get('/users', function(req, res){
request.getUsers()
.then(function(users){
console.log(users);
res.contentType('application/json');
res.send(JSON.stringify(users));
})
.catch(function(){
console.log(users);
});
});
module.js
exports.getUsers = function(){
var params = {search_string:""};
var users = [];
return new Promise(function(resolve, reject){
var result = connection.Users.get(params, function(error,response)
{
var user = [];
for(let i = 0; i < response.data.length; i++)
{
user = response.data;
}
users.push({user});
});
if(result != null)
{
console.log(result);
resolve(result);
}
else
{
reject(new Error('Try Again'));
}
});
}
When I run the server I get the typeError: expecting a function but got [object object]
I did not really get what is wrong.
How could I return an array from my module to my API using promises?
EDIT:
app.get('/users', function(req, res){
request.getUsers()
.then(function(users){
console.log(users);
res.contentType('application/json');
res.send(JSON.stringify(users));
})
.catch(function(){
console.log("not resolved");
});
});
My problem now is actually that I am getting the .catch even before any request is made the at /users endpoint and I dont know why.
In module.js you used new Promise() constructor but the input parameter should be a function and not an object, so to fix that use:
return new Promise(function(resolve, reject) {
var result = connection.Users.get(params, function(error,response)
...
});
Notice its not new Promise({function(...) but new Promise(function(...)) ...
Read more here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise
Edit:
I have modified your code to work to fix the second problem:
exports.getUsers = function(){
var params = {search_string:""};
var users = [];
return new Promise(function(resolve, reject){
var result = connection.Users.get(params, function(error,response) {
if(error || !response)
{
// report error
reject(new Error('Try Again'));
}
else
{
//process response
var user = [];
for(let i = 0; i < response.data.length; i++)
{
user = response.data;
}
users.push({user});
// report success
resolve(users);
}
});
}
You need to call resolve or reject inside connection.Users.get(params, function(error,response) {
Modify your module.js code as below. You passed an object instead of a function.
register.getUsers = function () {
var params = { search_string: "" };
var users = [];
return new Promise(function (resolve, reject) {
var result = connection.Users.get(params, function (error, response) {
var user = [];
for (let i = 0; i < response.data.length; i++) {
user = response.data;
}
users.push({ user });
});
if (result != null) {
console.log(result);
resolve(result);
}
else {
reject(new Error('Try Again'));
}
});
};
you declared user variable as an array and inside the for loop isn't useful because the user variable is always equals to response.data
if response.data is array of JSON object you can push it to users array inside loop
for (let i = 0; i < response.data.length; i++) {
users.push(response.data[i]);
}
I guess you want to return the array of objects
also I recommend you to use bluebird module to return promises
and also you can use Promise.mapSeries instead of for loop like:
return Promise.mapSeries(response.data, item => {
users.push(item)
})

Resources