haveacigaro haveacigaro - 2 months ago 8
Javascript Question

Why does .json() return a promise if in an object literal?

I've been messing around with the fetch() api recently, and noticed something which was a bit quirky.

let url = "http://jsonplaceholder.typicode.com/posts/6";

let iterator = fetch(url);

iterator
.then(response => {
return {
data: response.json(),
status: response.status
}
})
.then(post => document.write(post.data));
;


post.data returns a promise object.
http://jsbin.com/wofulo/2/edit?js,output

However if it is written as:

let url = "http://jsonplaceholder.typicode.com/posts/6";

let iterator = fetch(url);

iterator
.then(response => response.json())
.then(post => document.write(post.title));
;


post here is a standard object which you can access the title attribute.
http://jsbin.com/wofulo/edit?js,output

So my questions is: why does response.json return a promise in an object literal, but return the value if just returned?

Answer

Why does response.json return a promise?

Because you receive the response when all headers have arrived. Calling .json() gets you a promise for the body of the http response that is yet to be loaded. See also Why the response object from JavaScript fetch API is a promise?.

Why do I get the value if I return the promise from the then handler?

Because that's how promises work. The ability to return promises from the callback and get them adopted is their most relevant feature, it makes them chainable without nesting.

You can use

fetch(url).then(response => 
    response.json().then(data => ({
        data: data,
        status: response.status
    })
).then(res => {
    console.log(res.status, res.data.title)
});

or any other of the approaches to access previous promise results in a .then() chain to get the response status after having awaited the json body.