How does the inventory comparison function work?

const checkInventory = (order) => {
return new Promise((resolve, reject) => {
setTimeout(() => {
let inStock = order.every(item => inventory[item[0]] >= item[1]);
if (inStock) {
resolve(Thank you. Your order was successful.);
} else {
reject(We're sorry. Your order could not be completed because some items are sold out.);
}
}, 1000);
});
};


I couldn’t figure out what’s going up there.

  1. first, what’s the use of this expression ‘inventory[item[0]] >= item[1])’. This seems like an array but ‘inventory’ is an object.
  2. what kind of function declaration is this? Is this a loop?
  3. And what’s the use of a success handler and a failure handler if all they do is; to log or return resolve() a reject(). This can be even accomplished by passing the executer function into the promise.
22 Likes

As you can see checkInventory is a function which takes order as an argument. See in file app.js that we are actually passing an array of array to this function. order.every is used to apply a function on every value of that particular object which in this case is an array.
Inside order.every number of a particular item of the inventory is compared with the demanded value. If every asked item is sufficient in quantity then the promise is resolved otherwise rejected.

12 Likes

1: first, what’s the use of this expression ‘inventory[item[0]] >= item[1])’. This seems like an array but ‘inventory’ is an object.

You’re right, inventory is an object. We’re using the square bracket notation to access one of its properties.

Here item is an order item like ['sunglasses', 1]: an array with an item name and quantity. So item[0] is the name of an inventory item like “sunglasses.”

That means in inventory[item[0]], we are doing something like inventory['sunglasses'] - accessing inventory’s sunglasses property, the value of which would be the amount of sunglasses in stock.

So we are making sure the item quantity in stock (inventory[item[0]]) is at least equal to the quantity on the order (item[1])).

2: what kind of function declaration is this? Is this a loop?

No, not a loop but rather arrow functions.

You could rewrite that code segment like this without arrow functions:

function checkItemInStock(item) {
  return inventory[item[0]] >= item[1];
}

function checkAllItemsInStock(resolve, reject) {
  let inStock = order.every(checkItemInStock);
  if (inStock) {
      resolve("Thank you. Your order was successful.");
  } else {
      reject("We're sorry. Your order could not be completed because some items are sold out.");
  }
}

function executePromise(resolve, reject) {
  setTimeout(checkAllItemsInStock(resolve, reject), 1000);
}

function checkInventory(order) {
  return new Promise(executePromise);
}

3: And what’s the use of a success handler and a failure handler if all they do is; to log or return resolve() a reject().

I think the practical benefit of the handlers would be if they’re doing something more complex than logging.

The other benefit is that checkInventory stays focused on just checking inventory, and doesn’t worry about logging to the console or anything else.

73 Likes

(item => inventory[item[0]] >= item[1]);

this method comparing if both arrays match . can some one explain in details please/how ?

what value is taking this index here? > [item[0]] / number of items in inventory ? if so, how they compare match of names ?

8 Likes

I’m also confused by

setTimeout(() => {
let inStock = order.every(item => inventory[item[0]] >= item[1]);

I understand it’s looking at the array in app.js, but why is it specifying “inventory” when “inventory” is an object in library.js? And the inventory object does not contain an array, so I don’t understand why it is referring to one after pointing towards the inventory object.

Could someone also clarify why this is being called inside a setTimeout? I think the point is to push it to the bottom of the code but I’m not sure exactly why we are doing this.

Thanks!

5 Likes

The full line of code you’re looking at is:

let inStock = order.every(item => inventory[item[0]] >= item[1]);

Here it is broken down a bit:

  • order: an array of order items
  • item: an order item
  • inventory[item[0]] >= item[1]: whether an item is in stock
  • order.every(...);: returns whether all order items are in stock

item here is an order item. All the order items are arrays with 2 elements: (1) item name, (2) quantity ordered. (Example item: ['sunglasses', 1].)

inventory is an object whose properties are inventory item names, and the values are how many of each item is in stock. (Example property: sunglasses: 1000.)

Keeping that example item and property in mind, you could “translate” your code segment like this:

item => inventory[item[0]] >= item[1] //Original code
['sunglasses', 1] => inventory[item[0]] >= item[1] //Replaced item
['sunglasses', 1] => inventory['sunglasses'] >= 1 //Replaced item[0] and item[1]
['sunglasses', 1] => 1000 >= 1 //Replaced inventory[item[0]]
['sunglasses', 1] => true //"Translated" code

So for order item ['sunglasses', 1], whether it is in stock is true (because we have 1000 sunglasses in stock and we only ordered 1).

If this is true for all the order items, then order.every(...) will return true, making inStock also true.


If it makes things clearer, you could take that entire line:

let inStock = order.every(item => inventory[item[0]] >= item[1]);

and rewrite it like this instead:

let inStock = (() => {
    //Check whether all items on the order are in stock in our inventory.
    for (let i = 0; i < order.length; ++i) { 
        //Get order item.
        const item = order[i];

        //Get the name of the order item.
        const itemName = item[0];

        //Get the quantity we have in inventory of that item.
        const quantityInStock = inventory[itemName];

        //Get the quantity ordered of that item.
        const quantityOnOrder = item[1];

        //Make sure we have enough of that item in stock.
        const itemInStock = quantityInStock >= quantityOnOrder;

        //If this particular item isn't in stock, stop checking and return false.
        if (!itemInStock) { return false; }
        
        //Otherwise, continue the loop and make sure the next order item is in stock.
    }

    //If we made it here, that means all the order items were in stock.
    return true;
})();
59 Likes

why couldn’t it have just been

let inStock = order.every(item => inventory[item] >= item[1]);

Shouldn’t that work too or would inventory[item] just be the object property name instead of the value of the object property?

Can someone help me to understand the indexing that is happening on this line?

let inStock = order.every(item => inventory[item[0]] >= item[1]);

I’m confused about what appears to me to be a mismatch in the index which just my not understanding what is really happening here.

thanks,

josh

1 Like

The every iterator returns a boolean. It will be true if every item in an array meets the condition.

Above, element 0 is compared to element 1 and cannot be less than else the return will be false. We’re assuming that inventory is made up of smaller arrays with at least two elements each.

There is nothing amiss with the indices.

 > a = [[3,2],[3,3],[3,1]]
<- (3) [Array(2), Array(2), Array(2)]
 > a.every(x => x[0] >= x[1])
<- true
 > b = [[3,4],[3,3],[3,1]]
<- (3) [Array(2), Array(2), Array(2)]
 > b.every(x => x[0] >= x[1])
<- false
8 Likes

thanks that helped a lot!

1 Like

Thank a lot man! This part is super clear and tells everything about the logic!

2 Likes

You can’t use inventory[item] because then you are not gonna get the name of the order for example: bags or sunglasses. Instead you will get something like this ['sunglasses, 2]. But you need JUST NAME to reach the values in the inventory object.

Let’s take for example the first item of the order arrray.

  • inventory [item] => inventory [‘sunglasses’, 2] => probably cause an error, because there is no keys called “sunglasses , 2” in inventory object.

  • inventory [item][0] => inventory [‘sunglasses’, 2][0] => inventory[sunglasses] => it will reach the value of the sunglasses inside inventory object. Therefore, the function can compare 2 values each other.

Hope it helps.

3 Likes

Thank you very much for such a perfect explaination!

1 Like

not gona lie, if it weren’t for your posts i’d be stumped too. Thanks @tensor2 :):laughing:

inventory[item[0]] = “sunglasses: 1900”;
item[1] = order item[1] = 1;

2 Likes

So i tried re-uesd the same comparison function but without using a promise object with setTimeout, i also changed some names just to see if it would work. It wouldn’t work. Here you can see that it should be logging We're sorry. Your order could not be completed because some items are sold out. as i am clearly out of watches inside the “retailer” object. Instead its saying Thank you. Your order was successful. ??? Does anybody know why this is happening? I even tried this code in brackets IDE and got the same result :frowning:

    if (true)

should be,

    if (inStock)
checkRetailer
 > const retailer = {
       watches: 0,
       shoes: 1088,
       hats: 1144
   }
<- undefined
 > let online = [['watches', 12]];
<- undefined
 > function checkRetailer(x) {
       let inStock = x.every(y => retailer[y[0]] > y[1]);
       if (inStock) {
           console.log(`Thank you. Your order was successful.`)
       } else {
           console.log(`We're sorry, your order could not be completed because some items are out of stock.`)
       }
   }
<- undefined
 > checkRetailer(online)
   We're sorry, your order could not be completed because some items are out of stock.
<- undefined

@mtf i tried inStock, it wern’t working so i done is true

That is not a condtional, but a definite so the outcome will always be as you have seen. The code sample above is nearly identical to your posted screenshot, and gave the correct outcome. That should mean something.

I figured it out just now. Thanks. Just needed a break :slight_smile:

1 Like

The most confusing subject on the JavaScript course is this Promise, The way it’s been taught is just not clear at all. I have been lost from the beginning, this very class is the height of it, Just giving boxes to check without understanding what’s happening :expressionless: :unamused: :pensive:

2 Likes