zadees
zadees

Reputation: 123

Chaining .then functions in ES6 fetch call

I have been looking for a way to figure this problem out and apologize if my searching skills are not up to par.

My Issue: I am fetching an API and I want to know when all of the data has been fully loaded. Reading through the docs, it appears that I can chain .then statements with fetch and I thought that would work. But, it appears that they all seem to fire at the same time without waiting for the previous .then to finish.

Here's my code:

fetch(myUrl, {
    method: 'post',
    headers: {
       'Content-Type': 'application/json; charset=utf-8',            
     },
    credentials: 'include',         
    body: data
    })                                
        .then(fetchStatus)  
        .then(json)  
        .then(function(msg){                                    
            showSearchResults();
            setTimeout(function(){ console.log("Next then should fire after this"); }, 4000);                                   
        })
        .then(function(){
            return console.log("The 2nd is firing!");                                  
        });

function fetchStatus(response) {  
    if (response.status >= 200 && response.status < 300) {  
        return Promise.resolve(response)  
    } else {  
        return Promise.reject(new Error(response.statusText))  
    }  
}

function json(response) {  
    return response.json()  
}

This is great if it is asynchronous, but these events need to be synchronous due to the fact that I am trying to work with content that is created by the previous call, showSearchResults();

Any help is much appreciated.

Upvotes: 1

Views: 4070

Answers (1)

dillonius01
dillonius01

Reputation: 204

Chaining a .then does not guarantee that code will execute sequentially unless you have returned a promise from the previous .then call. In your example, if you want the second console.log to execute after showSearchResults, you should return showSearchResults() and chain your .then off of that (this only works if showSearchResults returns a promise; if it does not, you will want to wrap it in one similar to how you have for fetchStatus).

Similarly, if you want to chain a .then off of a setTimeout, you could write something like:

fetch(url, { method: 'post', etc... })
   .then(fetchStatus)
   .then(json)
   .then(function(msg){
      return new Promise(function(resolve, reject){
         setTimeout(function() {
            console.log("Next then fires after promise resolves");
            resolve();
         }, 4000)
       })
    })
    .then(function(){
       console.log("Second is firing")
    })
    .catch(err => console.log(error)) // always remember to catch errors!

Upvotes: 6

Related Questions