Search code examples
javascriptasynchronouspromisees6-promise

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.


Solution

  • 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')
    })