FAQ: JavaScript Promises - Avoiding Common Mistakes

It works if you run “node app.js” twice in the bash terminal. Don’t know why. Does anyone know why that would be, since it doesn’t specifically say to run it twice in the exercise? Thanks very much.

1 Like

I was having that exact same trouble on a few lessons, it took a while before that hit me; but yes, some people may have to run it twice.

I want to know also! I like the concise way of writing it without using return

1 Like

Hey @codedcolt & @glennlaw

It’s now over a year ago when I did this, and I can’t look back at the exercise to check what it was exactly that suggested the more concise syntax was incorrect, because I’ve no longer got the Pro subscription :wink:

Anyway, I’m more experienced now, and looking back over the posts it seems like it may be the fact that the “checking algorithm” is only allowing one of the possible alternative solutions for this exercise. I can’t be 100% certain without looking back at the actual exercise, but in terms of syntax, the following two alternatives do exactly the same thing:

checkInventory(order)
   .then(resolvedValueArray => processPayment(resolvedValueArray))
   .then(resolvedValueArray => shipOrder(resolvedValueArray))
   .then(successMessage => console.log(successMessage))
   .catch(errorMessage => console.log(errorMessage));

With arrow function syntax, the curly brackets and the return keyword can be omitted if the function body only contains a single return statement. The promises are still being returned, it’s just that the arrow syntax allows us to omit the return keyword. Notice, that we can also omit the curly braces from the functions with console.log statements instead of return statements. For me, this second version is much clearer than the first, and it also produces code which is much more concise.

The following, even more concise, third alternative should also work. We are still returning the promises, but in this case we need to look back at the processPayment() and shipOrder() functions to see the actual parameters and return statements, because we are referencing just the function names within each .then() . So some might argue that this makes the code harder to understand.

checkInventory(order)
   .then(processPayment)
   .then(shipOrder)
   .then(successMessage => console.log(successMessage))
   .catch(errorMessage => console.log(errorMessage));
2 Likes

I am having trouble with the last couple sections. I can have the exact same thing as the get solution but I continually get errors. In this section, I get the following error with the exact same code as the get solution answer.

restart the terminal

My code works, I removed the two common mistake but it keeps saying my code is wrong. I’m returning the values and chaining the .then()

checkInventory(order)
    .then((resolvedValueArray) => processPayment(resolvedValueArray))
    .then((resolvedValueArray) => shipOrder(resolvedValueArray))
    .then((successMessage) => {console.log(successMessage)});

(All the code above is unchanged)

Hi guys, I could not understand the below point. Can anyone explain it to me.

We invoke a second .then() . It’s supposed to handle the logic for the second promise, but since we didn’t return, this .then() is invoked on a promise with the same settled value as the original promise!

Based on what @jon_morris wrote earlier, it looks like you no longer need to return it, now that we have Arrow function expressions and the return is implied.
Edit: It could be that the lesson keeps saying to use return since it’s needed in cases that you have more than one line :man_shrugging:

1 Like

I had the same question, so I went to the MDN website (Promise.prototype.then() - JavaScript | MDN) and found this description of the return value of a then() method:

Once a Promise is fulfilled or rejected, the respective handler function ( onFulfilled or onRejected ) will be called asynchronously (scheduled in the current thread loop). The behavior of the handler function follows a specific set of rules. If a handler function:

  • returns a value, the promise returned by then gets resolved with the returned value as its value.
  • doesn’t return anything, the promise returned by then gets resolved with an undefined value.
  • throws an error, the promise returned by then gets rejected with the thrown error as its value.
  • returns an already fulfilled promise, the promise returned by then gets fulfilled with that promise’s value as its value.
  • returns an already rejected promise, the promise returned by then gets rejected with that promise’s value as its value.
  • returns another pending promise object, the resolution/rejection of the promise returned by then will be subsequent to the resolution/rejection of the promise returned by the handler. Also, the resolved value of the promise returned by then will be the same as the resolved value of the promise returned by the handler.

In this case, our named handler functions both call processPayment and shipOrder which both return a fulfilled promise, but if they just call them without actually returning their respective return values, what gets returned is a promise resolved with undefined. The problem is that the next handler in the chain requires an array as its input value, so this breaks the chain. Other than that, I don’t really see what the problem is with not having an explicit return statement.

1 Like

I think @board7302290096 has done a really good job at explaining why there has been a lot of confusion about this, here. :muscle:

I would just add that, where you use arrow function syntax AND you only have one parameter, you don’t need to place the parameter within parentheses. So, instead of …

… you can have …

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

and

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

This lesson is confusing. So the ‘mistakes’ are not really mistakes, they’re just less readable but still work? What?

The main problem is:

  • We invoke a second .then(). It’s supposed to handle the logic for the second promise, but since we didn’t return, this .then() is invoked on a promise with the same settled value as the original promise! :point_left:
returnsFirstPromise()
.then((firstResolveVal) => {
  returnsSecondValue(firstResolveVal)
})
.then((someVal) => {
  console.log(someVal);
})

There isn’t any oneline arrow func in this example. But there is a reference to " If the appropriate handler is not provided, instead of throwing an error, .then() will just return a promise with the same settled value as the promise it was called on." on the page 5/11.
And i think there is a small mistake in THIS lesson. First .then() gives us APPROPRIATE handler, but this handler doesn’t return anything. Second .then() is invoked on return of the first .then(()=>()), but there isn’t return and second .then() get undefined value and console.logs “undefined”. Not ‘’.then() is invoked on a promise with the same settled value as the original promise!". This might be true if the first .then() doesn’t contain handler at all.

1 Like

Thats what confused me.
The second .then() should receive ‘undefined’ if nothing is returned from the first .the().

1 Like

Did somebody else got the same successful result before and after doing the exercise? I mean, with the then()'s nested and their lacks of returns it worked for me in the same way that after refactoring it.

Yes, but the overall conclusion is that whether we use …

or …

or just …

… all of these 3 alternatives will either return the appropriate resolved value or throw an error. The fact that the 2nd and 3rd examples don’t include the keyword return doesn’t mean they will return undefined. Whether or not we need to explicitly include the keyword return in our code in order to achieve this outcome, purely depends on whether we have also used curly braces.

With ES6 arrow function syntax:

  • We are only required to enclose our function body within curly braces if it consists of more than one statement; and
  • If the function includes curly braces and we want it to return a value, then our return statement must begin with the return keyword; however,
  • If the function body only consists of one return statement, then this return statement doesn’t have to begin with the return keyword in order to return a value.