I have a fetch()
call in function myFetch()
(returns the fetch
‘s return value), and would like to wrap it in another function callApi()
. My goal is to make callApi()
return a Promise, such that:
- A "resolve" state indicates success (the fetch call returned response.ok / HTTP 200).
- In this case, I would like the value (of promise) to be the body/text of the response.
- A "reject" state indicates any failure during the process, which could be:
- There is something wrong with the fetch call, e.g. a GET request with body.
- In this case, I would like the message of reject to be that error.
- The fetch succeeded, but the upstream response is not HTTP 200.
- In this case, I would like the message of reject to be
status_code: body
wherestatus_code
andbody
are both from the HTTP response. - In fact, it does not have to be in this form, as long as the caller of
callApi()
can reconstruct this same message.
- In this case, I would like the message of reject to be
- There is something wrong with the fetch call, e.g. a GET request with body.
However, I do not know how to write the callApi()
function. My attempt only ended up with this (where myFetch()
is the call to fetch
):
return new Promise(
(resolve, reject) => {
myFetch()
.then((response) => {
if (response.ok) {
resolve(response);
} else {
reject(`${response.status}: ${response.text}`);
}
}, (error) => {
reject(error);
});
}
);
As you see, response.text
is a Promise, but I need the string there.
How can I achieve my goal?
In addition, if I also need to receive JSON response (from the fetch
), will there be any difference?
2
Answers
To obtain the response body as a string, you can modify your code as follows:
response.text()
returns a Promise that resolves to the response body as a string. By chaining another.then()
callback to it, you can access the body and pass it to either resolve or reject based on the response’s ok status.As for the JSON responses, you might want to use
response.json()
method instead ofresponse.text()
. This method returns a Promise, which resolves to the parsed JSON data instead of just text. Here’s an updated version of the code that handles JSON responses:When the response isn’t successful, the reject function is called with an object containing the response status and the parsed JSON error body. This allows the caller of
callApi()
to access both the status code and the response body in a structured manner.More information:
You shouldn’t create a new promise with
new Promise
when you already have a promise — the one returned bymyFetch
.Secondly, you’ll need to call the
text
method on the response, and construct the string when that returned promise resolves.It may be easier to use
async
await
syntax:Here the returned promise will never reject. If you want the promise to reject unless the response status is ok, then leave out the
try..catch
wrapper, and do:When you want to use the
json
method instead oftext
, then you’d want to produce an object instead of a string, and then it might be a better idea to always return an object that has the same toplevel keys:The version that will never return a promise that rejects:
The version that will reject the promise when the response is not ok: