FAQ: JavaScript Promises - Chaining Multiple Promises

Thanks for the help.Gotcha <3

1 Like

where is the .then (rejection) function in the example to the Left??? is it not needed?

1 Like

Did you found an answer to this?
My best regards,

can anyone please explain whats happening here!!

const shipOrder = (responseArray) => {

const order = responseArray[0];

const trackingNum = responseArray[1];

am really confused!!

1 Like

I’m learning too and I could be wrong. Someone please verify this.

In library,js, both processPayment and shipOrder have responseArray as parameters.

The resulting promise from checkInventory will be passed into then() as resolvedValueArray and then into then()'s callback function processPayment as the argument for responseArray .

processPayment will then return a promise that is passed into the next then() in the chain as resolvedValueArray, which passes it into the callback function shipOrder as the argument for responseArray.

Promises are extremely confusing :dizzy_face: :exploding_head:, i don’t understand what is going on in any lessons, can someone please share any other easy resources to understand promises ?

Guys, I have a question regarding this code:

const store = {

sunglasses: {

inventory: 817, 

cost: 9.99

},

pants: {

inventory: 236, 

cost: 7.99

},

bags: {

inventory: 17, 

cost: 12.99

}

};

const checkInventory = (order) => {

return new Promise ((resolve, reject) => {

setTimeout(()=> {

const itemsArr = order.items;

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

if (inStock){

 let total = 0;   

 itemsArr.forEach(item => {

   total += item[1] * store[item[0]].cost

 });

 console.log(`All of the items are in stock. The total cost of the order is ${total}.`);

 resolve([order, total]);

} else {

 reject(`The order could not be completed because some items are sold out.`);

}

}, generateRandomDelay());

});

};

const processPayment = (responseArray) => {

const order = responseArray[0];

const total = responseArray[1];

return new Promise ((resolve, reject) => {

setTimeout(()=> {

let hasEnoughMoney = order.giftcardBalance >= total;

// For simplicity we’ve omited a lot of functionality

// If we were making more realistic code, we would want to update the giftcardBalance and the inventory

if (hasEnoughMoney) {

 console.log(`Payment processed with giftcard. Generating shipping label.`);

 let trackingNum = generateTrackingNumber();

 resolve([order, trackingNum]);

} else {

 reject(`Cannot process order: giftcard balance was insufficient.`);

}

}, generateRandomDelay());

});

};

const shipOrder = (responseArray) => {

const order = responseArray[0];

const trackingNum = responseArray[1];

return new Promise ((resolve, reject) => {

setTimeout(()=> {

 resolve(`The order has been shipped. The tracking number is: ${trackingNum}.`);

}, generateRandomDelay());

});

};

// This function generates a random number to serve as a “tracking number” on the shipping label. In real life this wouldn’t be a random number

function generateTrackingNumber() {

return Math.floor(Math.random() * 1000000);

}

// This function generates a random number to serve as delay in a setTimeout() since real asynchrnous operations take variable amounts of time

function generateRandomDelay() {

return Math.floor(Math.random() * 2000);

}

module.exports = {checkInventory, processPayment, shipOrder};

My Question:
What is happening here resolve([order, total]); in checkInventory function?

i think ‘order’ that we passing in is a nested list.

order= [[suglasses,2], [pants,1]]

so each item here is a list/array i.e [suglasses,2] and item[0] = sunglassses

Bit confused with this part.


checkInventory(order)
.then((resolvedValueArray) => {
  // Write the correct return statement here:
 return processPayment(resolvedValueArray);
})
.then((resolvedValueArray) => {
  // Write the correct return statement here:
  return shipOrder(resolvedValueArray);
})
.then((successMessage) => {
  console.log(successMessage);
})
.catch((errorMessage) => {
  console.log(errorMessage);
});

I have looked for the ‘resolvedValueArray’ throughout the code, butcan’t find it, so I am assuming they aren’t real values, just placeholder terms like ‘firstResolvedValue’ etc. Although the it all seems to work as a real chain of promises when I enter ‘node app.js’

What is happening here?

Probably the confusion is about the difference between parameters and arguments, of functions. resolvedValueArray is just a parameter of an arrow function.

1 Like

let hasEnoughMoney = order.giftcardBalance >= total;

I want to understand how we can access order.giftcardBalance when the order array is app.js and the above line of code is in library.js and there is no importation done from app.js, yet giftcardBalance is accessible.

Good question! I see your point.

Like it was commented above, the issue that is easy to confuse is parameters vs arguments, as well as defining/declaring a function vs invoking/calling a function.



When you declare a function, you’re talking to your new employee, J.S., and explaining them what their task will be, what tools they will need, like: well, JS, you will need an array passed to you, the first item will be an object, and will have a property like this. It is like if you’re explaining the new employee the tasks they will do and the tools they will receive.

Part of these tools that they will receive are called parameters, but for now, you’re not giving them the tools, just explaining them what tools they will receive and how to work with them when the time comes.

Example of declaring a function:

function JSTaskAtWork(tool1, tool2) {
    // ...will have to do this
    // ...take tool1, it will have this feature, use it like that
    // ...take tool2, check that it's clean first
    // ...return a value, for example
}

Or you could also do this like:

const JSTaskAtWork = (tool1, tool2) => {
    // ...same as above here
}


Time passed, J.S. decided to sign the employment contract, and today is the day where the young J.S. will finally start actually working at the company. What changes? Well, now there’s no talking or explaining, now J.S. will have to take the tools and do their job, right?

That is what happens when you call/invoke the function. Calling the function is like being at work and being asked to do that task that they explained you before. Now, there’s no explaining, that’s why the wording is way shorter.

Example:

JSTaskAtWork(actualTool1Here, actualTool2Here);

And now, there’s no explaining the tools/parameters, you only receive the actual tools that you’ll use (the arguments). But these need to be at your disposal, otherwise you cannot do you job now. This is when it would matter to have access to the args.



Now, how does that apply in this case? You may have noticed it already, but anyway let’s analyze it. Well, in library.js the order object is being used only as part of “that explanation” in the definition of the function (on top of that, it is inside a promise, but that’s a whole other thing). It is not actually being used at that moment, only “explained” in the definition of the function. Now, if you take a look at app.js, do you notice the difference? It is called there, not defined. There is no explaining. The function there is being given a tool/value and has to do the work now.

Hope that helped clarify that a little bit further.

1 Like

I get what you mean but how can the giftcardBalance key be accessed from library.js when clearly the order object was declared in app.js. Is it because it was declared in the global scope and therefore can be accessed from another file?

Sorry, I think my example may not have been the best, it’s just the weird way in which I understand things (believe it or not it is :smiley: ) but of course, everyone has different ways to learn.
TLDR:
To be honest, what I think is that in this particular situation, you don’t call the function that uses the order object in the library.js. You only call it in app.js. So, it is in this file when you have to be sure to have access to the order object and thus to its giftcardBalance key.
TLDR ends here



Side note:
To understand it even better, you can try this:
open you dev tools, go to console and write this:

const aFunctionsWithObjects = obj1 => {
    let a = obj1.a.really.really.nested.key.here;  
    return a; 
};

No problem, right? No errors, no issues.

Now, copy that code, open a new tab and open the dev tools console again there. Add this line at the end:

aFunctionsWithObjects(myObj);

Have you received ReferenceError? Why? myObj is not defined it may say.

You are trying to call the function, hence the arg is checked (the param not).

1 Like

Ohhhhh okay I understand now, thanks for your help. Your example was great btw and I appreciate it. The function was called in app.js, thats the answer I needed. Thanks once more.

1 Like

Hello! Not a simple topic. That’s why I don’t understand why it’s presented through such a complicated example … It’s much easier to understand the promise than to break down the elements of the example. There are many videos on youtube that are more illustrative. e.g. https://youtu.be/670f71LTWpM Sorry for the criticism, but otherwise it is not typical of the learn materials of Codecamy. I still like you :kissing_heart:
(e.g. it would be more understable:

let inStock = itemsArr.every(orderItem => store[orderItem[0]].inventory >= orderItem[1]);

const order = {
items: [
[‘sunglasses’, 1],
[‘bags’, 2],
]

order.items.every((item) => store[item[0]].inventory >= item[1]);

store[item[0]].inventory >>> store.sunglasses.inventory >>> 817
item[1] >>> 1

817 >= 1 === true

For anyone else smashing their head off a wall because of this:

Both examples work and are functionally identical! The issue here is the wording of the accompanying text.

I took it to mean, as I think @ran16 did, that if you don’t use an arrow function callback with “return” that the code won’t work. T|his is not the case.

All the text is really saying is that if you format it with the arrow function and (this is the important bit) CURLY BRACES, because of the way JS works, you need to use the keyword “return” or the function won’t return anything.

This:

.then((resolvedValueArray) => {
return processPayment(resolvedValueArray);
})

And this:

.then((resolvedValueArray) => processPayment(resolvedValueArray))

And this:

.then(processPayment)

all do exactly the same thing! The text is just reminding you that if you use first of the three, you need to include the word “return” because JS implicity returns (returns without needing to use the “return” keyword) the results of calling an arrow function BUT does not implicitly return if you use the curly braces, as they do in their example.

The reason Codecademy prefers the longer version is that it’s more readable. I know that sounds weird, just using .then(processPayment) looks way simpler but if your promise resolves to multiple values it can be really handy for bugfixing to know which values you’re passing in to the next function. If you’re working on your own on a small project, by all means use .then(function) but if you’re working professionally, with other devs, I would recommend .then(response => function(response)), with or without the curly braces and “return”.

4 Likes

Nice explanation.

I assume this refers to this paragraph in the text of the lesson.

" In order for our chain to work properly, we had to return the promise secondPromiseFunction(firstResolveVal) . This ensured that the return value of the first .then() was our second promise rather than the default return of a new promise with the same settled value as the initial."

I could not understand it because it is a word salad. :slight_smile: It would have been better, if Codecademy had stated what the options are and why or why not to use a particular option.

1 Like

It seems to me that a fair few exercises have been written by someone who doesn’t have English as their first language. This can lead to ambiguities like the one mentioned. Not an issue if you know what you’re doing but can cost a learner multiple hours trying to reconcile the (incorrect or ambigious) instruction with the code. Not great from Codecademy, has happened to me about half a dozen times so far.