-1

I have this axios call with a nested axios call that causes async problems. Here's a simplifyed snippet of my code:

axios.all([
    axios.get('https://foo..', {
        headers: { 'Content-Type': 'application/json' },
        data: { 'endpoint': 'v2/bar..' },
    }),
]).then(axios.spread((resp) => {
    var resp = resp.data.content;
    var items = resp.items.slice(0, 1);
    items.forEach(item => {
        var dataUrl = item.url.split('/v2/').slice(1).join('');
        axios.get('https://foo..', {
            headers: { 'Content-Type': 'application/json' },
            data: { 'endpoint': 'v2/' + dataUrl + 'bar..' }
        }).then(resp => {
            const data = resp.data.content;
            // alot of code goes here
        }
        )
    }),
       axios.get('https://foo..' + pageNum.toString(), {
            headers: { 'Content-Type': 'application/json' },
            data: {}
        }
        ).then(resp => {
            fillTemplate(resp.data.content[0].xml);                   
        }
        ).catch(function (error) { console.log("DB-GET-Error:\n" + error) });
})
).catch(function (error) { console.log("error " + error) });

The problem is that 'fillTemplate()' executes before 'items.forEach(...)' is done and can populate 'fillTemplate()' with data, how can I solve this?

Pierre
  • 59
  • 5
  • either use async/await or execute last request in then() of a last request from for each – Milan Markovic Nov 20 '19 at 09:30
  • @MilanMarkovic I looked up async/await in tutorials but couldn't figure out how to implement it into my code, do you have an example how I can do it? – Pierre Nov 20 '19 at 09:34

1 Answers1

0

Problem

Both requests are send async and second won't wait for first one. Solution is to use async/await or Promise.all().

Escaping the callback hell

You are still having the problem of deeply nested code, which becomes unreadable. Below are two examples, first just fixing the issue and second with better readability.

Sample Code

axios.all([
  axios.get('https://foo..', {
      headers: { 'Content-Type': 'application/json' },
      data: { 'endpoint': 'v2/bar..' },
  }),
]).then(axios.spread((resp) => {
  // cache axios promises here
  var promises = []
  var resp = resp.data.content;
  var items = resp.items.slice(0, 1);
  items.forEach(item => {
      var dataUrl = item.url.split('/v2/').slice(1).join('');
      var promise = axios.get('https://foo..', {
          headers: { 'Content-Type': 'application/json' },
          data: { 'endpoint': 'v2/' + dataUrl + 'bar..' }
      }).then(resp => {
          const data = resp.data.content;
          // alot of code goes here
      });

      // add promises to array
      promises.push(promise);
  });

  // wait for all promises to execute next request
  Promise.all(promises).then((results) => {
    axios.get('https://foo..' + pageNum.toString(), {
      headers: { 'Content-Type': 'application/json' },
      data: {}
  }).then(resp => {
      fillTemplate(resp.data.content[0].xml);                   
  }).catch(function (error) { console.log("DB-GET-Error:\n" + error) });
  });
})).catch(function (error) { console.log("error " + error) });

Refactored version

axios.all([doStuff()]).then(axios.spread((resp) => {
  var promises = []
  var resp = resp.data.content;
  var items = resp.items.slice(0, 1);
  items.forEach(item => {
      var dataUrl = item.url.split('/v2/').slice(1).join('');
      var promise = doOtherStuff();
      promises.push(promise);
  });

  Promise.all(promises).then(finalCallback).then(resp => {
    fillTemplate(resp.data.content[0].xml);                   
  });
}));

function doStuff() {
  return axios.get('https://foo..', {
    headers: { 'Content-Type': 'application/json' },
    data: { 'endpoint': 'v2/bar..' },
  });
}

function doOtherStuff() {
  return axios.get('https://foo..', {
    headers: { 'Content-Type': 'application/json' },
    data: { 'endpoint': 'v2/' + dataUrl + 'bar..' }
  }
}

function finalCallback(results) {
  return axios.get('https://foo..' + pageNum.toString(), {
    headers: { 'Content-Type': 'application/json' },
    data: {}
  });
}
oshell
  • 8,923
  • 1
  • 29
  • 47