Not updating, but the promise return success - javascript

The update is not working, but the promise is returning success. I think it may be with the Where in the sequelize query not finding the value from the array of objects productsCodeArr.
const orderid = req.params.orderid
const productsCodeArr = convertedInputs.map(code => {
return ({
id: code.id,
picked: code.picked,
notPicked: code.notPicked
});
})
if(productsCodeArr) {
db.Detallepedido.update({
pickeado: productsCodeArr.picked,
nopickeado: productsCodeArr.notPicked
},
{
where: {
pedido_id: orderid,
producto_id: productsCodeArr.id
}
})
.then(() => {
console.log('Success!');
}})
.catch(reason => {
console.log(reason);
})

I did it!
I used Promise.all with a map of the array.
Promise.all(productsCodeArr.map(object=>{
return db.Detallepedido.update({
pickeado: object.picked,
nopickeado: object.notPicked
},
{
where: {
pedido_id: orderid,
producto_id: object.id
}
})}))

Related

Promise resolves before loop completes in sails

I have a list of posts containing userId. When fetching n no.of post, I want to loop throught and get and fetch user data and append them into the post.
But before the loop gets resolved, the function gets return with undefined. After that, the post data gets listed but I want the post data to be fetched first.
I am new to promises and async. If there are any other solutions that I can use, then please notify me.
I am using sailsjs.
fetchPosts: async (req, res) => {
let feeds = [];
posts = await Posts.find({
skip: offset,
limit: limit,
sort: sort,
});
if (posts) {
/**
* LOOPING THROUGH FETCHED POST LOOP TO GET
* USER DATA, LIKE, SHARE, FOLLOW, BOOKMARKS
*/
const functionWithPromise = (post) => {
//a function that returns a promise
console.log(feeds);
return Promise.resolve(post);
};
const anotherAsyncFunction = async (post) => {
return functionWithPromise(post);
};
const getUser = async (userId, post) => {
return new Promise(async (resolve, reject) => {
const user = await Account.findOne({ id: userId });
if (user) {
post = {
...post,
user: {
id: user.id,
uName: user.uName,
provider: user.provider,
dpURL: user.dpURL,
provider: user.provider,
},
};
resolve(post);
} else {
reject(null);
}
});
};
const anAsyncFunction = async (post) => {
if (post.isAdminPost) {
post = {
...post,
user: {
id: "5f3b8bf00dc3f12414b7f773", // this is usedid of admin#dopaminetalks.com in `Admin` model
uName: "DTOfficial",
provider: "LOCAL",
dpURL: "/dpURL/86a73b80-babc-4caa-a84c-762f6e9c1b36.png",
},
};
feeds = [...feeds, post];
return anotherAsyncFunction(feeds);
} else {
getUser(post.userId, post).then((post) => {
feeds = [...feeds, post];
return anotherAsyncFunction(feeds);
});
}
};
const getData = async () => {
return Promise.all(posts.map((post) => anAsyncFunction(post)));
};
getData().then((data) => {
console.log(data);
return res.json({
status: true,
msg: "Posts Fetched",
data: data,
});
});
}
},

Return a Child Promise func for a variable in Parent Promise func?

I have an issue with a Promise function. I use NodeJS + sequelizeJS
I have a Child Promise function to get User Data in table auth_user:
function sequelize_user (id_in) {
var promises = []
var querydb = `SELECT * FROM auth_user WHERE id IN (${id_in})`;
promises.push(
db.sequelize.query(querydb, { type: db.sequelize.QueryTypes.SELECT})
.then(res => {
return res
})
)
return Promise.all(promises);
}
And I have a Parent Promise function to get Conversation, which have participants as a User.
function sequelize_conversation (conversation_id, req) {
var promises = [];
for (let id of conversation_id) {
promises.push(
db.ConversationPerson.findAll({ where: {'conversation_id': id, 'user_id': { [Op.ne]: req.user.user_id }} })
.then(participants => {
if (cvs_person.length) {
return {
'conversation_id': id,
'with_user': (function() {
sequelize_user(cvs_person.user_id)
.then(user => {
console.log(user) // -> { id: 1, username: 'feedgit' }
return user // -> {} ?????????
})
})()
}
} else {
return { 'conversation_id': id }
}
})
);
}
return Promise.all(promises);
}
In this code:
'with_user': (function() { sequelize_user([participants[0].user_id]) .then(user => { console.log(user); return user }) })()
I want to get User by using Child Promise function sequelize_user but it returns {}. This is not true.
What's wrong with my code? I think it's because wrong Promise Function Calling.
You seem to be looking for
db.ConversationPerson.findAll({
where: {'conversation_id': id, 'user_id': { [Op.ne]: req.user.user_id }}
}).then(participants => {
if (cvs_person.length) {
return sequelize_user(cvs_person.user_id).then(user => {
// ^^^^^^ ^^^^^
console.log(user) // -> { id: 1, username: 'feedgit' }
return {
// ^^^^^^^^
conversation_id: id,
with_user: user,
// ^^^^
};
});
} else {
return { 'conversation_id': id }
}
})

POST request based on array of GET requests

I have array of customers and addresses endpoint URL as below
customerArray = [
{name:customer1, id: 1, address: {streetName: '123 lane'}},
{name:customer2, id: 2, address: {streetName: 'xyz lane'}},
{name:customer3, id: 3, address: {streetName: 'abc lane'}}
]
URL = 'id/addresses'
GET request for URL will return array of addresses based on customer ID
if we get empty array as response then we need to add address from "customerArray" for that id
// This is what I am doing to meet the requirement - seems this is not the right approach. Please help me to fix this
customerArray.forEach((customer) => {
const getObj = {
url: `${customer.id}/addresses`,
method: GET
};
axios(getObj)
.then((getResult) => {
if (getResult.length === 0) {
const postObj = {
url: `${customer.id}/addresses`,
method: POST,
data: customer.address
};
axios(postObj)
.then((postResult) => {
// I am not sure what to do here - I leaving blank so iteration will continue
})
.catch((err) => {
res.status(400).json(err);
});
}
})
.catch((err) => {
res.status(400).json(err);
});
});
Please help me to fix it
I think you don't know how to get the final data. Basically, you should put your promises into an array and you Promise.all to wait for all of them to finish.
Please comment if something wrong. Hope this helps
const promises = customerArray.map((customer) => {
const getObj = {
url: `${customer.id}/addresses`,
method: GET
};
return axios(getObj)
.then((getResult) => {
if (getResult.length === 0) {
return {
url: `${customer.id}/addresses`,
method: POST,
data: customer.address
};
}
return null;
})
.then((postObj) => {
if (postObj) {
return axios(postObj)
}
return null
})
});
Promise.all(promises)
.then(result => {
// the result is a list of data from axios(postObj)
console.log(result);
res.json(result);
})
.catch((err) => {
res.status(400).json(err);
});

Mongoose promise in foreach failed in my case

How to do promise with forEach? I want to get all jobs, but get the data of applicants. My Job schema already have the applicant id, but how to query the user and merge their detail in the output?
Job.find({}).then(result => {
result.forEach(obj =>{
const applicant_id = obj.applicant._id
if(applicant_id){
User.findOne({_id: applicant_id})
.then(user=>{
return res.json({
status: 1,
data: {
...obj,
applicant: {
...user
}
}
})
})
}
})
}).catch(err => {
if(err){
return res.status(400).send({
msg: err
})
}
})
I tried Promise but I'm stuck merging user into the Job obj,
Job.find({}).then(result => {
let promiseArray = []
result.forEach(obj =>{
const applicant_id = obj.applicant._id
if(applicant_id){
promiseArray.push(
User.findOne({_id: applicant_id}))
}
})
return Promise.all(promiseArray)
}).then(user => {
console.log(user)
//this work but this is only the user's data,
//I need it to be within obj which is Job data
})
You first need to filter items in result to exclude those without applicant id, then map this array to array of promises, and finally pass it to Promise.all. This should do it:
Job.find({}).then(result => {
const promises = result
.filter(obj => obj.applicant._id)
.map(obj => {
const applicant_id = obj.applicant._id
return User.findOne({ _id: applicant_id })
.then(user => {
return res.json({
status: 1,
data: {
...obj,
applicant: {
...user
}
}
})
})
})
return Promise.all(promises)
}).catch(err => {
if (err) {
return res.status(400).send({
msg: err
})
}
})
Here's a tested and working solution:
Job.find({ applicant: { $ne: null } }).populate('applicant').then(result => {
res.send(result);
}).catch(err => {
return res.status(400).send({
msg: err
})
});

The right way to do multiple MongoDB operations

If I need to perform two or three different operations on a few collections, is there a better way than chaining together find/update operations? For example:
db.collection('contactinfos').findOneAndUpdate(
{ _id: ObjectID(contactID) },
{ $set: { sharedWith } }
).then(response => {
db.collection('users').update(
{ _id: { $in: sharedWith.map(id => ObjectID(id)) } },
{ $addToSet: { hasAccessTo: contactID } },
{ multi: true }
).then(response => {
db.collection('users').update(
{ _id: { $in: notSharedWith.map(id => ObjectID(id)) } },
{ $pull: { hasAccessTo: contactID } },
{ multi: true }
).then(response => {
return res.send({ success: true });
}).catch(err => {
logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err);
return res.status(400).send({ reason: 'unknown' });
});
}).catch(err => {
logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err);
return res.status(400).send({ reason: 'unknown' });
});
}).catch(err => {
logger.error(`in updating sharing permissions for ${contactID} by user ${_id}`, err);
return res.status(400).send({ reason: 'unknown' });
});
It just seems messy and there has to be some better way of doing it. Furthermore, if there is an error after the first findOneAndUpdate that prevents the other updates from running, then there will be inconsistent data across documents. The documents contain ID references to other documents for faster lookup.
Also, is there a way to catch all errors within a chain of promises?
From your callback hell I can see you do not use response argument of .then() method anywhere. If you do not need results of one query to perform another, consider using Promise.all() method:
const updateContactInfo = db.collection('contactinfos')
.findOneAndUpdate(
{ _id: ObjectID(contactID) },
{ $set: { sharedWith } }
);
const updateUsers = db.collection('users')
.update(
{ _id: { $in: sharedWith.map(id => ObjectID(id)) } }, //hint: use .map(ObjectId) instead.
{ $addToSet: { hasAccessTo: contactID } },
{ multi: true }
);
const updateUsers2 = db.collection('users')
.update(
{ _id: { $in: notSharedWith.map(id => ObjectID(id)) } }, //hint: use .map(ObjectId) instead.
{ $pull: { hasAccessTo: contactID } },
{ multi: true }
);
Promise
.all([updateContactInfo, updateUsers, updateUsers2])
.then((values) => {
const updateContactInfoResult = values[0];
const updateUsersResult = values[1];
const updateUsers2Result = values[2];
return res.send({ success: true });
})
.catch((reason) => {
logger.error(`msg`, reason);
return res.status(400).send({ reason: 'unknown' });
});
Promise.all() will continue executing following .then() only if all the promises do resolve, otherwise it'll fall into the .catch() method. As of error handling, you can easily chain multiple .catch() methods, which is nicely explained here.
If you cannot have any data inconsistency, either:
Get some SQL database with transactions (easier solution)
Look into MongoDB Two-Phase Commit
And if it is acceptable to happen, let's say once per 1kk times, do include checking it's consistency within your app's logic.

Categories