How does `.then` know what to pass?

In the example for this exercise, the handleSuccess function takes in a variable and logs it to console. My first question is how does the prom.then function know which handle function to pass through? Since the resolvedValue variable doesn’t explicitly refer to the resolve outcome, how does it know what to log to console?

let prom = new Promise((resolve, reject) => {
let num = Math.random();
if (num < .5 ){
resolve(‘Yay!’);
} else {
reject(‘Ohhh noooo!’);
}
});

const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};

const handleFailure = (rejectionReason) => {
console.log(rejectionReason);
};

prom.then(handleSuccess, handleFailure);

My second question is does order matter? If I flip the order of handleSuccess and handleFailure so that it is:
const handleFailure = (rejectionReason) => {
console.log(rejectionReason);
};

const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};

prom.then(handleSuccess, handleFailure);
Does the prom.then function still pass the correct handles?

17 Likes

Did anyone reply to this question yet? I also wonder how the .then() method knows which handle to use for resolve/reject. I swapped them in the syntax but the result remains the same so somehow the method knows which one is which not just by the order they appear in, I just don’t get how.

5 Likes

It actually is just based off the order of the arguments. :slight_smile: The first function you pass in will always be used for resolve, the second for reject.

It is a bit confusing in the example, because even if you do swap the arguments, the result is the same. But that’s just because the success function and failure function do exactly the same thing: take in a message and print it to the console.

You can modify the functions a little to make it easier to see which one is being called, by adding “Success” or “Failure” to the start of the message:

const handleSuccess = (resolvedValue) => {
    console.log(`Success: ${resolvedValue}`);
};

const handleFailure = (rejectReason) => {
    console.log(`Failure: ${rejectReason}`);
};

Then, you can try swapping them around in the .then(). You should see the first function you pass to then() is always used as the resolve function, even if it says “failure,” and vice versa.

44 Likes

Hello guys,
I have a question related to part 6, specifically to this example:

04

If ‘handleSuccess’ and ‘handleFailure’ are functions that take in one argument, why when they are inserted in ‘then(handleSuccess, handleFailure)’ don’t take any arguments?

I’ve the doubt that’s a stupid question but I must resolve this.

Thanks for your answer.

6 Likes

callbacks do not take arguments because they are not invoked when passed in. Only the representation of the function is given. The then method will invoke the one that matches the outcome. The first callback is for success, the second for failure. then decides which to use and gives the appropriate argument at that time.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Using_promises

14 Likes

Thank you, that’s clear now.

2 Likes

I don’t think I fully understand this code in the example:

const prom = new Promise((resolve, reject) => {
resolve(‘Yay!’);
});

const handleSuccess = (resolvedValue) => {
console.log(resolvedValue);
};

prom.then(handleSuccess); // Prints: ‘Yay!’

Is an anonymous function being declared inside the Promise() function instead of declaring it separately and then passing it into Promise() like we did before?

Also, how does it know what to pass in for the “resolvedValue” parameter?

3 Likes

The .then method will take answer of the promise function (in this case, prom), and if it was resolved, pass it in to the first callback function (in this case, handleSuccess) and if it was rejected, pass it in to the second callback function (in this case, handleFailure)

4 Likes

I am fairly certain that the method does not “know” anything. Both handleFailure() and handleSuccess() do exactly the same thing, they log the parameter that was given to them by checkInventory() to the console. That means that it doesn’t matter which comes first, the outcome is the same, even if you delete one callback function (i.e you invoke checkInventory(order).then(handleFailure), for example).
However, I really don’t know what the creator of this exercise wanted to show us when she/he created it…

I’m having a hard time comprehending why callback functions do not need arguments, still the necessary arguments somehow show up just when we need them to. Could you kindly explain this, or provide a link to this topic? Thanks!

1 Like
const isEven = x => x % 2 === 0;
const isOdd = x => x % 2 !== 0;

const evens = [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(isEven);
const odds =  [1, 2, 3, 4, 5, 6, 7, 8, 9].filter(isOdd);

console.log(evens)    // [2, 4, 6, 8]

console.log(odds)     // [1, 3, 5, 7, 9]

We pass only a reference to the callback. The parameter x takes a value from the array as .filter iterates over it.

const parity = x => console.log(`${x} is ${x % 2 ? `odd` : `even`}.`);

[1, 2, 3, 4, 5, 6, 7, 8, 9].forEach(parity);

/*
1 is odd.
2 is even.
3 is odd.
4 is even.
5 is odd.
6 is even.
7 is odd.
8 is even.
9 is odd.
*/

Same thing as before. .forEach() iterates the array and passes the value to the callback parameter.

3 Likes

tysm :smiling_face_with_three_hearts:

First lets clarify on two different concepts:

  1. Function Definition:
 `    const exampleFunction=(name)=>{console.log(name)} // just defined, does nothing`
  1. Function Invocation:
    `  exampleFunction("Erfan")  // logs "Erfan"`

In JavaScript, function definitions can be passed to another function (“a higher-order function”) as a parameter, usually, we describe such a situation as “the function taking a callback”. The higher-order function then calls the callback according to its own implementation, and may or may not pass a value to it.

In your example, the method then of the prom is the higher-order function. it takes a callback, passes the resolved value to it, and calls it. it doesn’t care about its name, just looks for a function definition and calls it.

3 Likes

Thank you man! this really helped me understand this lesson!

Just for my own Clarification: So any function that takes a parameterized callback function generates the arg to pass to the callback function… For example, the addEventListener function instantiates an event object and passes it to the callback function, right? Do you know if the event object is always generated or is it only generated when the callback function has a parameter list? And also, if the callback function has more than one parameter, it’s the first parameter that gets passed the event object right? Like

function myFunction(x, y, z){}

myButton.addEventListener(“click”, myFunction);
then the x parameter gets initialized to new Event( ) ?

Can’t say for sure whether it’s a good idea to have multiple parameters on the handler. event, or even e is sufficient to identify the event object. There is never more than one event object in memory at a time and it is highly transient, lasting only until another event is fired.

If, as you suggest there are multiple parameters on the handler, I can’t see how the listener will know to include them in the handler call. This will undoubtedly mean more research and experimentation.

Oh yeah. So I was asking that if the callback function has three parameters for ex, would the first parameter get assigned to the listener generated event object? The other parameters would I guess be bound to the callback function using (Function.prototype.bind())

See if you can come up with an example that we can experiment with.

Maybe something like a restaurant menu page.

/*Script for a restaurant website. Gets order data from user and presents a receipt.
uses Function.prototype.bind to pass multiple args to an event handler's callback function
*/

//restaurant checkout receipt  check out button and array of menu item captions
const receipt = [];
const checkoutButton = document.getElementById('checkout-button');
const figCaptionArr = document.getElementsByTagName('figcaption');
//GetReceipt function pushes a menu item-name and cost to receipt. 
//figCaption is arr of captions that will be bound in the eventListener fn
const GetReceipt = (figCaption, target) =>{
    /*orderItems array populated with input element children of a 
 div container that represents a menu item.
 the div container also contains a figure img and figcaption element */
    const orderItems = document.getElementsByClassName("quantity-input");
    for(let i=0; i<orderItems.length; i++){
        //data-set atrribute is the price of the item. value attr is the quantity the user enters
        receipt.push(figCaption[i].innerHTML + " " +(input[i].value * input["data-set"]).toString() + "\n" );
    }
    //prints the receipt to the console
    console.log(receipt.join(""));
}

//add event listener with a callback function that takes multiple args!
checkoutButton.addEventListener("click", GetReceipt(figcaption, e)
//bind this as checkoutButton and the figcaptions to the getReceipt function
.bind(checkoutButton, figCaptionArr));

Can you put this in a REPL.IT so we can run it?