How can I do more optimal async/await using inside loop? - javascript

I want to do more optimal my code. I summeries to following code.I have a data access layer named
ICDataAccess.I making that get all inventorys firts line.Then I get locations of inventory response and I want to get all barcodes with locations information from ServiceCaller data access.Then this barcodes adds to each inventory of inventorys array.How can i do more optimal.Is there a logic error. Help me please...
const ic = await this.ICDataAccess.getActiveIC({ warehouse, locations, status: statuses }); // An object array
await Promise.all(ic.map(async (item) => {
const inventory = item;
const response = await ServiceCaller.filterStore({ ids: inventory.locations, fields: 'barcode' }); // An object array
inventory.barcodes = response.map(res =>res.barcode);
}));

Related

Unable to understand asynchronous functions in NodeJS

I have spent 6 hours already trying to figure out how to do this in NodeJS.
I am using NodeJS with Express and MongoDB.
I have a database that has two collections viz. Listings and Categories. Each listing has a "category" which is an ID that maps to a category inside the Categories collection.
What I want to do is, fetch all the listings, then loop through all of them, and get the category title from the Categories collection using the category id.
This is what I had for getting all the listings:
const listings_raw = [];
await db.collection("listings").find().forEach(listing => listings_raw.push(listing));
The code above works fine. The trouble I am having is with this:
const listings = [];
listings_raw.forEach(async listing => {
const category_id = listing.category;
const category_title = await db.collection('categories').findOne({_id: objectId(category_id)});
listing.category_title = category_title;
listings.push(listing);
});
response.send(listings);
The response.send(listings); gets executed before the listings_raw.forEach completes.
I want to send the data only after all listings have been populated with the category titles.
After spending 6 hours, I have come up with the following hack which I am sure is nasty!
const listings_raw = [];
const em = new events.EventEmitter();
await db.collection("listings").find().forEach(listing => listings_raw.push(listing));
const listings = [];
let counter = 0;
listings_raw.forEach(async (listing) => {
const category_id = listing.category;
const category = await db.collection('categories').findOne({_id: objectId(category_id)});
listing.category_title = category.title;
listings.push(listing);
if (counter === listings_raw.length - 1) {
em.emit('listings:processing:done');
}
counter++;
});
em.on('listings:processing:done', () => {
response.send(listings);
});
Please, can someone explain or guide me on how this should be done in JavaScript?
Basically, I am not able to figure out how to know if all promises have been resolved or not.
Thank you!
The listings_raw.forEach function executes synchronously on the array, even though you are then performing an asynchronous operation within that.
Promise.all will allow you to await for the result of an array of promises. Therefore you can .map the listings to an array of promises which return the updated listing.
const listings = await Promise.all(listings_raw.map(async listing => {
const category_id = listing.category;
const category_title = await db.collection('categories').findOne({_id: dependencies.objectId(category_id)});
listing.category_title = category_title;
return listing;
});
response.send(listings);

Unable to add object fetched from mongoDB to normal javascript array

I am trying to create an add to cart button which fetches the data from product database using the id of specific product which I selected. I am trying to push the object found using the same Id into a normal javascript array and then to display it using ejs methods. While I was tring I found I am unable to push the data in object form.
Summary:
On 7th line I have declared an array and in that array I want to store some objects which I have fetched frome a db model.
On 15th line I am trying to push the object form into my array so that I could iterate through the objects to display them on my page using ejs. But I am unable to do that.
screenshots:
Here's the final result I'm getting even after trying to push objects in array:
empty array logged
Here are the objects I'm trying to push:
Objects
Code:
app.get("/cart", (req, res) => {
if (req.isAuthenticated()) {
const findcartdata = req.user.username;
userData.findOne({email: findcartdata}, (err, BookId) => {
// console.log(BookId.cartItemId);
const idArray = BookId.cartItemId;
var bookArray = [];
idArray.forEach((data) => {
productData.findOne({_id: data}, (err, foundBookData) =>{
// console.log(foundBookData);
if(err){
console.log(err);
}
else{
bookArray.push(foundBookData);
}
})
});
console.log(bookArray);
// res.render("cart", {
// cartBookArray: BookId.cartItemId
// })
});
} else {
res.redirect("/login");
}
})
In above code i found the user's email using passport authentication user method and using that email I wanted to add the products in a different javascript array (which I am goint to pass to my ejs file of cart and then iterate it on list) using those array of Id which I got from another model called userData. The problem is I am able to find userData of each Id but unable to store them as an array of objects.
Looks like a timing issue, your code completes before the database downloads the objects and pushes them to your array.
This should fix your issue:
// ...
const idArray = BookId.cartItemId;
var bookArray = [];
for (const data of idArray) {
const foundBookData = await productData.findOne({_id: data}).catch(console.error);
if (!foundBookData) continue;
bookArray.push(foundBookData);
}
console.log(bookArray);
// ...
By the way, make sure to make the whole function asynchronous as well, which would be done by changing this line:
userData.findOne({email: findcartdata}, async (err, BookId) => { // ...

Delete item from CosmosDB

I'm trying to delete entries from Azure CosmosDB.
Documetation says:
/**
* Delete item
* Pass the id and partition key value to delete the item
*/
const { resource: result } = await container.item(id, category).delete();
console.log(`Deleted item with id: ${id}`);
My function to delete and items is:
// takes in an entry id to detete and deletes it with the documentation
async function findItemsToDelete(idToDelete){
const category = config.partitionKey; // partitionKey is {kind: "Hash", paths: ["/requests"]} and I've also tried just "/requests"
// the four lines below are correct
const { endpoint, key, databaseId, containerId } = config;
const client = new CosmosClient({ endpoint, key });
const database = client.database(databaseId);
const container = database.container(containerId);
// query to return item with id (random code to make sure the item exists)- not important
const querySpec = {
query: `SELECT * FROM c WHERE c.id = "${idToDelete}"`
};
const { resources: items } = await container.items
.query(querySpec)
.fetchAll();
// below is the delete code from the documentation
const { resource: result } = await container.item(idToDelete, category).delete();
// random array holding the item that was just deleted- not important
return items;
}
When I try calling this, I get an error that says: Entity with the specified id does not exist in the system. Does anyone know how to properly implement this? I know the id is correct but I believe I may be doing something wrong with the partitionKey/Category part.
I saw in this post: Cannot delete item from CosmosDB
that i may need the partition key value, but I dont know what that is or how to get it. Please let me know if you know what's going on!

Updating A Deeply nested Array of Objects inside a mongoose query

I am trying to update a mongoose document, But its a deeply nested array of objects and I am having trouble updating it using the spread operator. I have an array of image-links and I wanna iterate through the relationships array in the database and add an image to each relation. The code shows my approach, but the syntax is wrong. I have added a db image which shows where I wanna add the image variable.
// Get Images
const imagesData = await axios.get(
"https://randomuser.me/api/?results=4&gender=male"
);
const images = [];
imagesData.data.results.forEach((result) => {
images.push(result.picture.large);
});
// Update Company
for (let i = 0; i <= 3; i++) {
const updateCompany = await Companies.findByIdAndUpdate(
req.params.id,
{ relationships: [
...relationships,
relationships[i]: {
...relationships[i],
image: images[i]}
] },
{ new: true }
).exec();
}
Also I am using a mongoose query inside a for loop. Is it the right way to do it.
mognoDB
You should fetch the document that you want. Then treat the fetched object as a javascript object and add or update whatever you want then use .save() function provided by mongoose.
let result = await Companies.findById(id);
result = result.map((company)=>{
update your object here
})
result.save()
The .save() function will take care of updating the object in the database

Can I treat items found through a Promise.all as a firebase collection?

I am stuck in what I thought was a very simple use case: I have a list of client ids in an array. All I want to do is fetch all those clients and "watch" them (using the .onSnapshot).
To fetch the client objects, it is nice and simple, I simply go through the array and get each client by their id. The code looks something like this:
const accessibleClients = ['client1', 'client2', 'client3']
const clients = await Promise.all(
accessibleClients.map(async clientId => {
return db
.collection('clients')
.doc(clientId)
.get()
})
)
If I just needed the list of clients, it would be fine, but I need to perform the .onSnapshot on it to see changes of the clients I am displaying. Is this possible to do? How can I get around this issue?
I am working with AngularFire so it is a bit different. But i also had the problem that i need to listen to unrelated documents which can not be queried.
I solved this with an object which contains all the snapshot listeners. This allows you to unsubscribe from individual client snapshots or from all snapshot if you do not need it anymore.
const accessibleClients = ['client1', 'client2', 'client3'];
const clientSnapshotObject = {};
const clientDataArray = [];
accessibleClients.forEach(clientId => {
clientSnapshotArray[clientId] = {
db.collection('clients').doc(clientId).onSnapshot(doc => {
const client = clientDataArray.find(client => doc.id === client.clientId);
if (client) {
const index = clientDataArray.findIndex(client => doc.id === client.clientId);
clientDataArray.splice(index, 1 , doc.data())
} else {
clientDataArray.push(doc.data());
}
})
};
})
With the clientIds of the accessibleClients array, i create an object of DocumentSnapshots with the clientId as property key.
The snapshot callback function pushes the specific client data into the clientDataArray. If a snapshot changes the callback function replaces the old data with the new data.
I do not know your exact data model but i hope this code helps with your problem.

Categories

Resources