1

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.

7
  • 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. Commented Oct 2, 2017 at 15:59
  • try wrapping showSearchResults in Promise.all and wait for that to resolve Commented Oct 2, 2017 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?) Commented Oct 2, 2017 at 16:03
  • You will need to promisfy showSearchResults and return that promise within that then() callback Commented Oct 2, 2017 at 16:04
  • You need to wrap setTimeout into the promise: new Promise(resolve => setTimeout(() => { ...; resolve(); }, 4000)). Commented Oct 2, 2017 at 16:06

1 Answer 1

6

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! 
Sign up to request clarification or add additional context in comments.

1 Comment

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!

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.