0

I'm facing a bit of a weird situation and I can't spot the cause. I'm my server update order endpoint, I can either receive an orderState or an updatedOrder to update MongoDB record var { orderState, updatedOrder } = req.body;. As I'll be modifying updatedOrder in a for loop to update MongoDB, I also assign the received updatedOrder to a constant to be passed later on to Neo4j to do same updates and create relationships, as const modifiedOrder = req.body.updatedOrder; .

With an if/else statement I either update MongoDB Order record state parameter or the entire Order record. In the second case, when updatedOrder.cart item state property is found to be 'Refund requested', and accordingly to the property isPromotion to be true or false I first update Product and Promotion records, then update updatedOrder cart item state value to Refunded, in the mentioned for loop.

Then after the for loop I update the Order record with the updated updatedOrder.

The problem is that after the first loop modifiedOrder is also updated, so when sent to Neo4j cart item state is not 'Refund requested' but 'Refunded'.

How can it be that const modifiedOrder value is changed when modifying var updatedOrder? Even dough they get the initial value from req.body.updatedOrder a const should keep the first assigned value right?

Can you spot what I'm doing wrong?

var { orderState, updatedOrder } = req.body;
    const modifiedOrder = req.body.updatedOrder;
    console.log(
      '1> Mongoose updatedOrder received modifiedOrder.cart is',
      modifiedOrder.cart
    ); // correct 

if (orderState) {

...

} else if (updatedOrder) {

for (var i = 0; i < updatedOrder.cart.length; i++) {
          console.log(
            `LOOP> Mongoose updatedOrder before loop ${i} modifiedOrder.cart is
            ${modifiedOrder.cart}`
          ); 
          // at 1st loop (i = 0) CORRECT 1st item state is "Refund requested"
          // at second loop (i = 1) WRONG 1st item state is now "Refunded"

          var cartItem = JSON.parse(updatedOrder.cart[i]);
          if (cartItem.state == 'Refund requested') {
            if (cartItem.isPromotion == false) {
              await Product.findByIdAndUpdate(
                cartItem.id,
                {
                  $inc: { soldQuantity: -1, availableQuantity: 1 },
                },
                {
                  session: session,
                  new: true,
                },
                null
              )
                .clone()
                .exec()
                .then((result) => {
                  console.log(
                    'Mongoose Order.updateOrder / Product.update Inventory updated successfully for product:',
                    result.id
                  );
                  if (result != null) {
                    cartItem.state = 'Refunded';
                    totalRefundAmount += result.price;
                  } else {
                    cartItem.state = 'Not refunded';

                  }
                  return;
                })
                .catch((error) => {
                  if (error) {
                    console.log(
                      'Mongoose Order.updateOrder / Product.update error: ',
                      error
                    );
                    cartItem.state = 'Not refunded';
                    throw error;
                  }
                });
            } else if (cartItem.isPromotion == true) {
              await Promotion.findByIdAndUpdate(
                cartItem.id,
                {
                  $inc: { soldQuantity: -1, availableQuantity: 1 },
                },
                {
                  session: session,
                  new: true,
                }
              )
                .clone()
                .exec()
                .then((result) => {
                  if (result != null) {
                    totalRefundAmount += result.price;
                    cartItem.state = 'Refunded';
                    console.log(
                      'Mongoose Order.updateOrder / Promotion.update Inventory updated successfully for promotion:',
                      result
                    );
                  } else {
                    cartItem.state = 'Not refunded';
                  }
                  return;
                })
                .catch((error) => {
                  if (error) {
                    console.log(
                      'Mongoose Order.updateOrder / Promotion.update error: ',
                      error
                    );
                    cartItem.state = 'Not refunded';
                    throw error;
                  }
                });
            }
          }
          updatedOrder.cart[i] = JSON.stringify(cartItem);
        }



...
}

before 1st loop 1st item is "Refund requested":

LOOP> Mongoose updatedOrder before loop 0 modifiedOrder.cart is
            {"createdOnDate":1638894572905,"name":"testProduct","brand":"someBrand","price":12,"description":"description","category":"Safety and locks","city":"Bologna","region":"Emilia-Romagna","country":"Italy","vendor":"testShop","vendorId":"OrderTestShop","barcode":"some","imageUrl":"https://firebasestorage.googleapis.com/v0/b/fix-it-b4b00.appspot.com/o/Products%2F61af8bec02edbe24ce034963?alt=media&token=a891dc05-407e-43d2-ab2b-0f49226249a9","fullImages":[],"thumbNails":[],"minimumStock":10,"availableQuantity":10,"soldQuantity":0,"isPromotion":false,"totalRating":0,"ratings":0,"_id":"636a0c9e8145999716d71de2","createdAt":"2022-11-08T08:00:30.399Z","updatedAt":"2022-11-08T08:00:30.399Z","__v":0,"averageRating":0,"id":"636a0c9e8145999716d71de2","isRecommendation":true,"state":"Refund requested"},{"createdOnDate":1638894572905,"productId":"636a0c9e8145999716d71de2","name":"testPromotion","brand":"someBrand","price":12,"description":"new description","category":"Safety and locks","city":"Bologna","region":"Emilia-Romagna","country":"Italy","vendor":"testShop","vendorId":"OrderTestShop","barcode":"some","imageUrl":"https://firebasestorage.googleapis.com/v0/b/fix-it-b4b00.appspot.com/o/Products%2F61af8bec02edbe24ce034963?alt=media&token=a891dc05-407e-43d2-ab2b-0f49226249a9","fullImages":[],"thumbNails":[],"minimumStock":10,"availableQuantity":10,"soldQuantity":0,"isPromotion":true,"totalRating":0,"ratings":0,"_id":"636a0c9e8145999716d71de4","createdAt":"2022-11-08T08:00:30.467Z","updatedAt":"2022-11-08T08:00:30.467Z","__v":0,"averageRating":0,"id":"636a0c9e8145999716d71de4","isRecommendation":true,"state":"Bought"}

after first loop 1st item is "Refunded":

LOOP> Mongoose updatedOrder before loop 1 modifiedOrder.cart is
            {"createdOnDate":1638894572905,"name":"testProduct","brand":"someBrand","price":12,"description":"description","category":"Safety and locks","city":"Bologna","region":"Emilia-Romagna","country":"Italy","vendor":"testShop","vendorId":"OrderTestShop","barcode":"some","imageUrl":"https://firebasestorage.googleapis.com/v0/b/fix-it-b4b00.appspot.com/o/Products%2F61af8bec02edbe24ce034963?alt=media&token=a891dc05-407e-43d2-ab2b-0f49226249a9","fullImages":[],"thumbNails":[],"minimumStock":10,"availableQuantity":10,"soldQuantity":0,"isPromotion":false,"totalRating":0,"ratings":0,"_id":"636a0c9e8145999716d71de2","createdAt":"2022-11-08T08:00:30.399Z","updatedAt":"2022-11-08T08:00:30.399Z","__v":0,"averageRating":0,"id":"636a0c9e8145999716d71de2","isRecommendation":true,"state":"Refunded"},{"createdOnDate":1638894572905,"productId":"636a0c9e8145999716d71de2","name":"testPromotion","brand":"someBrand","price":12,"description":"new description","category":"Safety and locks","city":"Bologna","region":"Emilia-Romagna","country":"Italy","vendor":"testShop","vendorId":"OrderTestShop","barcode":"some","imageUrl":"https://firebasestorage.googleapis.com/v0/b/fix-it-b4b00.appspot.com/o/Products%2F61af8bec02edbe24ce034963?alt=media&token=a891dc05-407e-43d2-ab2b-0f49226249a9","fullImages":[],"thumbNails":[],"minimumStock":10,"availableQuantity":10,"soldQuantity":0,"isPromotion":true,"totalRating":0,"ratings":0,"_id":"636a0c9e8145999716d71de4","createdAt":"2022-11-08T08:00:30.467Z","updatedAt":"2022-11-08T08:00:30.467Z","__v":0,"averageRating":0,"id":"636a0c9e8145999716d71de4","isRecommendation":true,"state":"Bought"}
``

Vincenzo
  • 5,304
  • 5
  • 38
  • 96

1 Answers1

1

const obj = {
  key: 'value1'
};

const objShallowCopy = obj;
const objDeepCopy = JSON.parse(JSON.stringify(obj));

obj.key = 'value2';

console.log('objShallowCopy: ', objShallowCopy);
console.log('objDeepCopy: ', objDeepCopy);
Rocky Sims
  • 3,523
  • 1
  • 14
  • 19
  • HI and thanks for answering. yeap the const in js still gets me at times lol. Still just to make sure, I'm changing the value of `updatedOrder` which changes `req.body.updatedOrder` as well, thus `modifiedOrder ` gets changed as well. Correct ?? I thought about it, but thought that `req.body.updatedOrder` wouldn't get modified so ruled it out. Should have known better.. I do now! lol – Vincenzo Nov 08 '22 at 08:30
  • Correct, `updatedOrder` and `modifiedOrder` and `req.body.updatedOrder` all reference (point to) the same location in memory (in this case, an "order" object). Declaring something with `const` ensure that what value/object it references cannot be changed but it but it doesn't prevent changes to the values within that referenced object. – Rocky Sims Nov 08 '22 at 09:31
  • To phrase it differently, `const` creates an immutable _binding_, not an immutable value. – Sebastian Simon Nov 08 '22 at 09:47