Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Can I somehow get the fetch response in the first `then`?

I am trying to use the Fetch API. It seems from examples that a GET request needs one then to parse the response somehow.

Currently I am doing this

fetch(url)
    .then(response => response.json())
    .then(response => {
        console.log(response);  
    });

However that first then seems like a boilerplate. I tried to avoid it, for example:

fetch(url)
    .then(response => {
        console.log(response.json());  
    });

But this logs me a pending Promise with status resolved.

I read other questions on this topic and read a bit about promises, but I couldn't understand if it's possible to combine it in a single then (if so - how?) or not.

For example, two of the answers here point out that

There is no need to use more than one '.then'

and

there is no good reason to have two .then() handlers as the code from each could have been combined into a single .then() handler

But I couldn't get that example to actually work - I still got a promise :)

On the contrary, the accepted anwser here explains that .then actually does something to the result (extracts the returned from promise), but I couldn't unserstand if I can somehow do that myself, say response.json().then() or response.json().getVal() or is the double-then syntax the only way.

like image 265
Džuris Avatar asked Aug 29 '18 18:08

Džuris


2 Answers

It's quite simple: when you dispatch the a fetch() request, it returns a promise containing the response. That is resolved by the first .then(). Resolving this first promise actually returns Response.

Now this is the tricky part: the methods that read the body of the response, be it .json(), .text(), .blob().... all return promises. This means that you will need to resolve the second promise in order to get the parsed response.

The flow looks like this:

  1. Make a fetch() request, and it returns a Promise of type Response
  2. When you attempt to resolve the content of the Response, it will return a second Promise, whose type depends on the method you use (e.g. .json() returns an object, .text() returns string, .blob() returns Blob).
  3. Resolve the second Promise, and you get your actual parsed response body

p/s: If you're not using fetch() in a top-level context (as of the time of writing top-level await is still not a thing), then you can use async/await to make your code a little more readable:

const response = await fetch(url);
const content = await response.json();
console.log(content);
like image 60
Terry Avatar answered Nov 08 '22 09:11

Terry


The first promise returned by fetch can be useful in some cases. If you want to avoid boilerplate, you could simply create your own function:

function fetch_json(url, opts) {
    return fetch(url, opts)
        .then(resp => resp.json());
}

fetch_json(your_url)
    .then(json => console.log(json));
like image 33
Petr Broz Avatar answered Nov 08 '22 09:11

Petr Broz