0

I need to find a way when the request gets a 403 I can use if before calling JSON with status and data. Only 403 returns HTML

const response = await fetch(
  // Fetch info
).then((response) => {
  if (!response.ok && response.status === 403) {
    // Stuffs
    throw new Error('Exception message'); // Raise error to stop the code
  }

  return response.json();
})
.then((data) => ({
  // I need use status code again, and keep the if statement 403 on top.
  status: response.status, 
  data,
}));
Rory McCrossan
  • 331,213
  • 40
  • 305
  • 339
  • try { const response = await fetch(".."); console.log(response.status); if(response.ok) return response.json(); } catch(err) { /* do ur error logic here */} – Joel Oct 21 '22 at 07:55
  • Don't mix `await` and `then` syntax, they do not fail gracefully when used together. – Jeremy Oct 21 '22 at 07:58
  • @Jeremy "*hey do not fail gracefully when used together.*" what does that even mean? Rejecting from the promise chain will still raise an exception from the `await`. As usual. – VLAZ Oct 21 '22 at 08:00
  • @VLAZ Amongst other things, Promises uses `.then/.catch/.finally` for error handling whilst `await` uses `try catch` to deal with error handling. Jeremy is completely correct with this statement. How would one surface an error thrown within a `.then/.catch` clause to an outer scoped `try catch` ? – Joel Oct 21 '22 at 08:48
  • @Joel The way you use `try`/`catch` with `await` *requires* the promise to be rejected. `try { await f() } catch (e) {}` will go in the `catch` block if the promise from `f()` rejects. There are no multiple error mechanism - it's just one. Based on the state of the promise. An `await` either continues on fulfilled promise or raises an exception which goes to the `catch` block of a `try`/`catch` block. The `catch` block is mirrored by a `.catch()` handler. The semantics of the promise API follow the `try`/`catch` for maximum comaptibility https://jsbin.com/jalahijuqa/1/edit – VLAZ Oct 21 '22 at 09:06
  • @VLAZ have a read here https://dev.to/maximization/why-you-shouldnt-mix-promisethen-with-asyncawait-syntax-gl1 TLDR `promises have a different error handling mechanism than async/await`. – Jeremy Oct 21 '22 at 10:02
  • @Jeremy an article from somebody who obviously doesn't understand promises? Thanks, I don't really need it. I only had to scroll to this example: https://i.imgur.com/Bgkq1YV.png the correct answer is *neither*. Not really. The *correct code* would be to use `await Promise.update()` which will then do A. The B happens because you have *not* used `await` nor handled the rejection with `Promise.update().catch()`. That's really it. It's not a mystery. Nor is it some spooky extra mechanism. Essentially imagine there was a `Promise.reject("boom")` instead - it's very obviously not handled. – VLAZ Oct 21 '22 at 10:20

2 Answers2

1

If you want to keep with the .then() style you have rather than switch to only using await, you can just move the 2nd .then() to where you have response in scope:

const result = await fetch(...).then((response) => {
    if (!response.ok && response.status === 403) {
        throw new Error('Exception message');
    }    
    return response.json().then(data => {
        status: response.status,
        data
    });
});

Or, you can just use await and avoid the mixing of await and .then() which is generally less clear and should usually be avoided:

const response = await fetch(...);
if (!response.ok && response.status === 403) {
    throw new Error('Exception message');
}
const data = await response.json();
const result = {status: response.status, data};

Note, I've avoided using response in two separate places to mean two different things and used result for the final result and left response as the fetch() response.

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • 3
    Don't mix `async/await` with `.then/.catch` unless you have a VERY good reason. In this case, you don't. – Joel Oct 21 '22 at 07:56
  • @Joel this advice is to avoid confusion. There is no real reason to avoid it other than that. And this code does not seem confusing. – VLAZ Oct 21 '22 at 07:58
  • @Joel - I've already offered another option that doesn't mix them. The mixing came from the OP's question so I was just showing them how to adapt what they had. – jfriend00 Oct 21 '22 at 07:58
  • @VLAZ There's a big difference between the two. Promise is an object representing intermediate state of operation which is guaranteed to complete its execution at some point in future. Async/Await is a syntactic sugar for promises, a wrapper making the code execute more synchronously. i.e. await the response. Promise has 3 states – resolved, rejected and pending. Async await doesn't have any states. It returns a promise, either resolved or rejected. `promise.then(fn)` continues execution whilst `await` awaits. Error handling is `.then() and .catch() ` and for async `try catch`. I could go on – Joel Oct 21 '22 at 08:31
  • @Joel you're not describing any differences that matter. `x = await f();` is the same as `f().then(x => {})`. Mixing the two concept is not only *possible* it's literally the only way the code works if you ever use `await`. There are cases where you probably don't want to mix the two - when reading the code will be more confusing than needed. But just saying "they are different because they use different syntax" is missing the forest for the trees. – VLAZ Oct 21 '22 at 08:36
  • @VLAZ *"`x = await f();` is the same as `f().then(x => {})`"* No, it's not the same. Check here for a simple demo: https://stackblitz.com/edit/js-ljkrwn?file=index.js – Joel Oct 21 '22 at 08:41
  • @Joel are you trying to deliberately twist my words? https://stackblitz.com/edit/js-mfbfvw?file=index.js You *should* know that `await` is built on top of promises. You already said so with "Async/Await is a syntactic sugar for promises" and then suddenly give me what should pass as proof two do not work the same, yet you're using code that just doesn't try *even try* to do the same things. What are you trying to argue here ultimately? There is no incompatibility between async/await and promise API. – VLAZ Oct 21 '22 at 08:56
  • 1
    Loving the friendly discussion guys. Here is why you should not mix them https://dev.to/maximization/why-you-shouldnt-mix-promisethen-with-asyncawait-syntax-gl1 – Jeremy Oct 21 '22 at 10:04
1

response is an argument to your first callback, it's not in scope in the second.

It will be a lot easier if you stop using then (in general, there is hardly ever a good reason to mix async/await and then):

const response = await fetch(/* fetch info */)
if (!response.ok && response.status === 403) {
  // Stuffs
  throw new Error('Exception message') // Raise error to stop the code
}
const data = await response.json()
const result = {
  status: response.status, 
  data
}
CherryDT
  • 25,571
  • 5
  • 49
  • 74
  • I did not. You edited yours and verbatim copied mine. – CherryDT Oct 21 '22 at 08:07
  • I did not copy yours. – jfriend00 Oct 21 '22 at 08:07
  • 1
    See, so we just had the same (obvious) solution and were simultaneously typing it up :) – CherryDT Oct 21 '22 at 08:08
  • ...and if you don't believe me, you can check the timestamps. [I answered at 07:57:18](https://i.stack.imgur.com/maMO9.png) and [you added the solution in an edit to your answer at 07:58:19](https://i.stack.imgur.com/OUfT0.png), one minute and one second later. – CherryDT Oct 21 '22 at 08:16
  • 1
    It's...a very trivial and straight-forward transformation to go from promises to just `await` syntax. You end up with basically the same code. And the variable names are completely generic and *very* common for these use cases. So, I don't really think it was copied. – VLAZ Oct 21 '22 at 08:27