0

It seems that unfortunately I cannot find an answer to a seemingly easy beginner question (trying to learn some Javascript).

I have this code running in sample react app (this path at localhost doesn't exist):

const promise2 = axios.get('http://localhost:3001/foobar').then(response => {
   // do nothing
}).catch((err) => {
   console.log(promise2)
})

This logs Promise { <state>: "pending" } in Firefox Developer Edition (76.0b5)

If I change the code to

const promise2 = axios.get('http://localhost:3001/foobar')
promise2.then(response => {
   // do nothing
}).catch((err) => {
   console.log(promise2)
})

This logs Promise { <state>: "rejected" } as I think it supposed to in both cases.

Why?

user1264176
  • 1,118
  • 1
  • 9
  • 26
  • What are you actually trying to achieve? – jonrsharpe May 18 '20 at 21:16
  • 1
    Because in the first example promise2 is returned by the catch method which is not awaited by anyone. – Eldar May 18 '20 at 21:22
  • @jonrsharpe I am trying to understand why the promise in the first snippet is still `pending`. As I said I am learning Javascript and in my understanding the promise in catch block should be already "rejected" . – user1264176 May 18 '20 at 21:22
  • @Eldar is the `promise2` implicitly awaited in the second snippet by something because I assign `then` and `catch` blocks on assigned variable ? – user1264176 May 18 '20 at 21:26
  • 1
    No, the value assigned to promise2 is the promise that returned from catch method. – Eldar May 18 '20 at 21:29
  • @Eldar I think I begin to understand. So in the snippet 2 I have, let's call it "request promise" which I log later in catch block and which is rejected by then. And in the snippet 1 I have "another promise" which is returned by catch block and is not the same as the one which I called "request promise" above. Right? – user1264176 May 18 '20 at 21:34
  • I would like to say Yes but 12 more characters required. – Eldar May 18 '20 at 21:36
  • @Eldar thanks for your help. Just confirmed. Basically as I understand each of the `.then()` or `.catch()` method returns another Promise object and I thought it returns the same object to which you append a queue of closures (as in Alamofire in Swift). – user1264176 May 18 '20 at 21:38
  • @Eldar please add an answer so I could accept it if you hunt for reputation. – user1264176 May 18 '20 at 21:38
  • 1
    No, it's ok if it helped. – Eldar May 18 '20 at 21:39

2 Answers2

1

In your first example, promise2 is the result of calling:

const promise2 = axios.get(...).then(...).catch(...)

And, it's a new promise, different from just what axios.get() returns and it is NOT resolved until AFTER the .catch() or .then() handler runs because its resolved value or rejected reason is determined by what happens in the .then() or .catch() handler.

Each step in the chain returns a new promise that isn't resolved until every before it in the chain has resolved and until this particular handler has been executed (or bypassed).

So, in this chain:

const promise2 = axios.get(...).then(...).catch(...)

You get the first promise from axios.get(), then another one from .then(), then another one from .catch() and promise2 will be contain the final one from the .catch(). That final promise will not resolve or reject until the whole chain is done.


In your second example, promise2 is only the result of calling:

const promise2 = axios.get()

So, the promise2 value is known as soon as the axios() call is done and will be known by the time the .then() or .catch() handler is called in this:

promise2.then().catch()

P.S. I would appreciate if someone could point me (in the comments) to the rationale why these methods return new objects and what I could do with those new objects.

It has to do with how promise chaining works. In order to implement chaining of multiple .then() handlers where each of those handlers could themselves contain functions that return new promises, you need to create intermediate promises in the chain that are dependent on things that happen later in the chain.

Here are a few other relevant answers:

Understanding javascript promises; stacks and chaining

What is the order of execution in javascript promises

Is there a difference between promise.then.then vs promise.then; promise.then

You don't typically do anything with the intermediate promise objects yourself, they are mostly there to make promise chaining work properly. You would normally just do:

axios.get(...).then(...).catch(...)

and not assign any of the promises to any variables.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
0

Eldar (thanks!) helped me to understand what was the reason for unexpected (for me) log messages.

As I've learned, .then() and .catch() methods return a new and distinct Promise object. I mistakingly thought that I work with the same Promise object I've gotten from axios.get(...) and just append handlers to it.

To confirm that you can check this code:

const promise2 = axios.get('http://localhost:3001/foobar')
const promise21 = promise2.then(response => {
  // do nothing
}).catch((err) => {
   console.log(promise2)
   console.log(promise21)
})

Which logs:

Promise { <state>: "rejected" }   index.js:26
Promise { <state>: "pending" }    index.js:27

P.S. I would appreciate if someone could point me (in the comments) to the rationale why these methods return new objects and what I could do with those new objects.

user1264176
  • 1,118
  • 1
  • 9
  • 26