I'm trying to implement a payment gateway system into a project that I'm working on, and I need to get the cart total in the backend instead of just in the frontend. I'm trying to do this with forEach()
and reduce()
. The part that I am struggling with is filtering through _id
s from all of my products to then find the _ids
associated with my items in my cart (cartInfo
), and then from there getting the price of the items whose _ids
match the _ids
of the items in the cart. Below, I have included what I have so far. I would really appreciate any help or guidance on how to do this. Thank you!
const total = products.forEach(x => {
if (x._id === cartInfo._id) {
const itemsTotal = x.price * cartInfo.qty
}
})
const sum = itemsTotal.reduce((a, b) => a b, 0)
products
is an array of all of the products and cartInfo
contains the _id
s and qty
s of each of the products in the cart.
Example of cartInfo:
0: {_id: '624bc7fe0f91078261ab6529', qty: 1}
1: {_id: '624bc8240f91078261ab6531', qty: 2}
Example of products:
0: {_id: '624bc7fe0f91078261ab6529', name: sample 1, price: 30, countInStock: 10}
1: {_id: '624bc8240f91078261ab6531', name: sample 2, price 10, countInStock: 4}
2: {_id: '624bc1a50f91078261ab650d', name: sample 3, price 15, countInStock: 1}
3: {_id: '62562017645f1882e45adc32', name: sample 4, price 20, countInStock: 7}
CodePudding user response:
For readability and loop optimisation, I prefer the simple for...of
statement for these kinds of scenarios:
let cartInfo = [
{
_id: `624bc7fe0f91078261ab6529`,
qty: 1
},
{
_id: `624bc8240f91078261ab6531`,
qty: 2
},
];
let products = [
{
_id: `624bc7fe0f91078261ab6529`,
name: `sample 1`,
price: 30,
countInStock: 10
},
{
_id: `624bc8240f91078261ab6531`,
name: `sample 2`,
price: 10,
countInStock: 4
},
{
_id: `624bc1a50f91078261ab650d`,
name: `sample 3`,
price: 15,
countInStock: 1
},
{
_id: `62562017645f1882e45adc32`,
name: `sample 4`,
price: 20,
countInStock: 7
},
];
let cartTotalPrice = 0;
for (cartItem of cartInfo) {
for (product of products) {
if (cartItem._id === product._id) {
cartTotalPrice = (product.price * cartItem.qty);
break;
};
};
};
console.log(cartTotalPrice);
The readability aspect of this solution is subjective, but I just think this code looks a lot more human-friendly than methods and callback functions.
The for...of
statements used here will also provide the ability to break-out of a given loop with the break
statement. So in this context, if an item in the cart is matched to an item in products array in an iteration of the nested for...of
loop, that same cart item won't be queried against the products array again in subsequent loops. With this specific dataset and solution, this brings the overall loops down from 8 to 3. You can probably imagine that with larger cart sizes and product catalogues, the performance benefits would be pretty significant.
Hope this helps.
CodePudding user response:
So specifically using the methods you want to use. You could do something like so. The main thing I change though is iterating the cart first and then using the find method to match the cart id to the product id.
const cart = [{
_id: '624bc7fe0f91078261ab6529',
qty: 1
},
{
_id: '624bc8240f91078261ab6531',
qty: 2
}
]
const products = [{
_id: '624bc7fe0f91078261ab6529',
name: 'sample 1',
price: 30,
countInStock: 10
},
{
_id: '624bc8240f91078261ab6531',
name: 'sample 2',
price: 10,
countInStock: 4
},
{
_id: '624bc1a50f91078261ab650d',
name: 'sample 3',
price: 15,
countInStock: 1
},
{
_id: '62562017645f1882e45adc32',
name: 'sample 4',
price: 20,
countInStock: 7
}
]
const cartTotals = [];
cart.forEach((product) => {
const matchedProduct = products.find(element => element._id === product._id);
if (matchedProduct) {
cartTotals.push(product.qty * matchedProduct.price);
}
});
console.log(cartTotals)
const totalAmount = cartTotals.reduce((a, b) => a b, 0);
console.log(totalAmount);
CodePudding user response:
You can do it with a single forEach like this:
let total = 0;
cartInfo.forEach(productInCart => {
const product = products.find(productExtended => productExtended.id === productInCart.id);
total = product.price * productInCart.qty;
});
But I would suggest to store the product's price inside cartInfo, that way you will not need to access products at all when counting the total
CodePudding user response:
Try using reduce function
const total = cartInfo.reduce((totalValue, currentCartItem) => {
const foundProduct = products.find(product => product._id === currentCartItem._id);
if (foundProduct) {
totalValue = foundProduct.price * currentCartItem.qty
}
}, 0);
CodePudding user response:
Here is an example where you can get the subtotal for each item and then the total:
const cartInfo = [
{_id: '624bc7fe0f91078261ab6529', qty: 1},
{_id: '624bc8240f91078261ab6531', qty: 2}
]
const products = [
{_id: '624bc7fe0f91078261ab6529', name: 'sample 1', price: 30, countInStock: 10},
{_id: '624bc8240f91078261ab6531', name: 'sample 2', price: 10, countInStock: 4},
{_id: '624bc1a50f91078261ab650d', name: 'sample 3', price: 15, countInStock: 1},
{_id: '62562017645f1882e45adc32', name: 'sample 4', price: 20, countInStock: 7}
]
let subtotals = cartInfo.map(({_id, qty}) => {
return { _id, subtotal: qty * products.find(p => p._id === _id).price }
})
let total = subtotals.reduce((total, item) => item.subtotal total, 0)
console.log('Subtotals:', subtotals)
console.log('Total:', total)