0

I have this code (view on JSFiddle):

fetch('https://some.invalid.url').then(resp => resp.text())
.catch(err => console.log("got error: " + err))
.then(text => console.log("got text: " + text));

Currently this logs the two lines

"got error: TypeError: Failed to fetch"
"got text: undefined"

I would like it to only log the line

"got error: TypeError: Failed to fetch"

In other words, I would like the promise chain to end once the .catch is called and not go into the .then. How can I do this?

(I could throw an exception inside the .catch, but I think that results in a unhandledrejection event which is undesirable).

Kerrick Staley
  • 1,583
  • 2
  • 20
  • 28
  • Why not put the `.catch()` in the end? Do you want to not handle exceptions from the `.then()` handler? – Bergi Jun 22 '23 at 03:15
  • Yeah, I don't want my `.catch` to trigger if I throw an exception in the `.then`. – Kerrick Staley Jun 22 '23 at 06:54
  • Then [use `.then(…, …)`](https://stackoverflow.com/q/24662289/1048572) instead of `.then(…).catch(…)` or `.catch(…).then(…)` – Bergi Jun 23 '23 at 02:06

3 Answers3

2

Your issue is that your .catch() returns a resolved promise (resolving with the return value of console.log(), ie undefined).

Either move the .catch() to the end of the promise chain

fetch('https://some.invalid.url').then(resp => resp.text())
.then(text => console.log("got text: " + text))
.catch(err => console.log("got error: " + err));

or have it continue rejecting the chain (but note this will throw an uncaught promise rejection error)

fetch('https://some.invalid.url').then(resp => resp.text())
.catch(err => {
  console.log("got error: " + err);
  return Promise.reject(err);
})
.then(text => console.log("got text: " + text));
Phil
  • 157,677
  • 23
  • 242
  • 245
1

You need to swap the ordering so the .catch() is at the end of the chain.

fetch('https://some.invalid.url').then(resp => resp.text())
.then(text => console.log("got text should fail: " + text))
.catch(err => console.log("got error should fail: " + err));


fetch('https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js').then(resp => resp.text())
.then(text => console.log("got text that should succeed: " + text))
.catch(err => console.log("got error should succeed: " + err));

(view on JSFiddle)

0

Cancellable promises are not supported in ECMASCRIPT, but you could process catch clauses conditionally upon the type of error argument. E.G. Say you know every real error argument is non-null. Then you could

  1. Throw null in a catch handler after logging or processing a real error.
  2. Check if the err argument at the beginning of every catch handler to see if it is null. If so, re-throw the null error value immediately.
  3. At the end of the promise chain, put an additional catch handler that re-throws its argument if it is not null - to report uncaught errors during development.

Potentially this could be used to work around the absence of cancellable promises in JS - but I do not suggest using it without dire need. As comments have suggested, moving catch handlers to the end of the chain, or logging an error and re-throwing it in the same catch handler is the more common approach.

traktor
  • 17,588
  • 4
  • 32
  • 53