BruceM
BruceM

Reputation: 1729

How to process fetch() response and still work asynchronously

I have a JS program that does a whole lot of fetch() calls to a specific API. I want to abstract all the fetch() calls into a single class called "apiService" so my code will be more readable. I want the apiService to apply some intelligence and then return responses to the caller, in the following ways: - apiService should check the response to see if there are errors present, which it must always process in the same way. - fetch() will sometimes receive a "res" that is raw data and should be used as is, and sometimes it'll received json that needs a .then(res => res.json().then(res applied so it can return an object.

So I can't just do a "return fetch(..." from apiService, because apiService needs to process one or more .then() blocks with the response. But I also need to return something that causes the calling code to work asynchronously and not block and wait.

Anyone know how I could structure the apiService function to process the html responses but also return asynchronously i.e. the calling function would receive the result object after the error checking etc.

Upvotes: 2

Views: 2541

Answers (4)

Matt Way
Matt Way

Reputation: 33199

So I can't just do a "return fetch(..." from apiService, because apiService needs to process one or more .then() blocks with the response. But I also need to return something that causes the calling code to work asynchronously and not block and wait.

This gives me the feeling that you might be misunderstanding promises a little bit. Take this example:

const doAsyncWork = () => fetch('somewhere').then(() => console.log('fetch is complete'))
// use the above function
doAsyncWork().then(() => console.log('used the fetching function'))

The output of the above code will be

fetch is complete
used the fetching function

As you can see, by chaining then after the fetch call, you are actually returning the result of then, and not fetch. Another way to think of it is, what are you actually returning if you called

const result = a().b().c() // we are really returning the result of `c()` here.

With the above in mind you can most definitely do something like:

const apiCall = loc => fetch(loc).then(res => {
  // do things with your response

  return res
})

apiCall('someEndpoint').then(finalRes => {
  console.log('this is called after fetch completed and response processed')
})

Upvotes: 2

vijay krishna
vijay krishna

Reputation: 524

You can use a library called axios instead of worrying about promises and data formats yourself.

However, if you still want to do it, use the following way.

you can use a method to create promises like this.

 makeRequest(url, requestData) {

        const response = await fetch(url, requestData)
            .then(response => { console.info('network request successful to', url); return response.json() })
            .then(json => {
                console.info('response received for request', url, requestData, json)
                return json;
            })
            .catch(e => {
                console.error('error at request', url, requestData, e);
                return e
            });
        return response;
    }

and use the promises like this

makeRequest('someurl', {
            method: 'GET'
        }).then(response=>{/*Your logic*/}).catch(error=>{/*Your logic*/});

Upvotes: 0

Roopak Puthenveettil
Roopak Puthenveettil

Reputation: 1485

I thinks you can fulfill your requirement using Promise.all()

Here is an example for you.

var promise1 = Promise.resolve(3);
var promise2 = 42;
var promise3 = new Promise(function(resolve, reject) {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(function(values) {
  console.log(values);
});

For more info you can refer:

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Upvotes: 0

Barr J
Barr J

Reputation: 10927

There is a nice article about it here called "Synchronous" fetch with async/await that will break it down for you in pieces.

In Short:

You can use await when using fetch():

const response = await fetch('https://api.com/values/1');
const json = await response.json();
console.log(json);

First we wait for the request to finish, Then we can wait for it to complete (or fail) and then pass the result to the json variable.

The complete example would be to use async, because `await won't work without it:

const request = async () => {
    const response = await fetch('https://api.com/values/1');
    const json = await response.json();
    console.log(json);
}

request();

Upvotes: 0

Related Questions