0

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.

zadees
  • 113
  • 1
  • 8
  • If you're using ES6 don't forget about the `msg => { ... }` function notation. It can save a lot of verbosity and avoids the `var self = this` dance. – tadman Oct 02 '17 at 15:59
  • try wrapping `showSearchResults` in Promise.all and wait for that to resolve – maioman Oct 02 '17 at 16:01
  • It's unclear what the problem is here. You have a single `fetch` call, and each handler in that chain will run only after the previous one runs. What's the problem, exactly? (Also: Shouldn't you be providing some kind of argument to `showSearchResults`?) – T.J. Crowder Oct 02 '17 at 16:03
  • You will need to promisfy `showSearchResults` and return that promise within that `then()` callback – Patrick Evans Oct 02 '17 at 16:04
  • You need to wrap `setTimeout` into the promise: `new Promise(resolve => setTimeout(() => { ...; resolve(); }, 4000))`. – alexmac Oct 02 '17 at 16:06
  • Side note: `fetchStatus` can just `return response` in the "good" case, no need for `Promise.resolve(response);` `then` creates a promise, and resolves it with what you return. – T.J. Crowder Oct 02 '17 at 16:08
  • Thanks for all of your help. I ended up having to add a promise and the code dillonius01 gave is giving me the desired results. – zadees Oct 02 '17 at 16:29

1 Answers1

4

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!
dillonius01
  • 184
  • 1
  • 4
  • This works exactly as I was hoping for it to work. I tried this method before posting, but I didn't have the "new" keyword in my Promise and struggled with that for a while. Thank you for your help! – zadees Oct 02 '17 at 16:31