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 question is: why does response.json return a promise in an object literal, but return the value if just returned?
In addition to the above answers here is how you might handle a 500 series response from your api where you receive an error message encoded in json:
Also, what helped me understand this particular scenario that you described is the Promise API documentation, specifically where it explains how the promised returned by the
then
method will be resolved differently depending on what the handler fn returns:This difference is due to the behavior of Promises more than
fetch()
specifically.When a
.then()
callback returns an additionalPromise
, the next.then()
callback in the chain is essentially bound to that Promise, receiving its resolve or reject fulfillment and value.The 2nd snippet could also have been written as:
In both this form and yours, the value of
post
is provided by the Promise returned fromresponse.json()
.When you return a plain
Object
, though,.then()
considers that a successful result and resolves itself immediately, similar to:post
in this case is simply theObject
you created, which holds aPromise
in itsdata
property. The wait for that promise to be fulfilled is still incomplete.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 is the response object from JavaScript fetch API a promise?.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
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.