Wait for axios API call to complete in Node/Express

Viewed 1896

I'm certain that this code is a mess as I have never had to work with an API call such as this. The issue I'm facing is, in a production environment, node is not waiting for the axios call to complete before rendering the page.

I have no issues running it in the dev environment.

router.get('/:id', middleware.isLoggedIn, (req, res) => {
var perPage = 9
var page = req.params.page || 1
User.findById(req.params.id)
.populate({
    path : 'log',
    options : { 
        sort : { date : -1 },
        limit: 8,
        skip: (perPage * page) - perPage
    },
  }).exec((err, foundUser) => {
    if(err){
        req.flash('error', 'Something went wrong. User not found.');
        res.redirect('back');
    } else {
        Logbook.find({author: req.user.id}).countDocuments().exec((err, count) => {
            if (err) return next(err)
            axios.get('http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=' + foundUser.username + '&format=json')
                .then(async response => {
                    var json = response.data;
                    if (json == undefined || json.Licenses == undefined || json.Licenses.License == undefined) {
                        if (err) {
                            console.log(err);
                        }
                        console.log('error1');
                        res.redirect('/profile/' + foundUser.id);
                    } else {
                        var data = json.Licenses;
                        var data2 = data.License;
                        var lic = [];
                        for (var i = 0; i < data2.length; i++) {
                            var lic = data2[i];
                        }
                        res.render('profile/index', {
                            user: foundUser,
                            json: lic,
                            current: page,
                            pages: Math.ceil(count / perPage),
                            logCount: count,
                        });
                    };
                })
                .catch(error => {
                    console.log(error);
                    res.redirect('/profile/' + foundUser.id);
                });
        });
    }
});

Any help is sincerely appreciated!

1 Answers

Your async keyword is in a weird spot, and you haven't used await to indicate that node should be waiting for the result of that operation.

Generally speaking, you mark a function as async, and within that async block, you can await the results of the asynchronous operations.

async function asyncFunc() {
  try {
    const response = await axios.get("/some_url_endpoint");
    const data = await response.json();
    return data;
  } catch (error) {
    console.error(error);
  }
}

Your example could be rewritten like this:

async function searchLicenses(foundUser) {
  const { username, id } = foundUser;
  const url = `http://data.fcc.gov/api/license-view/basicSearch/getLicenses?searchValue=${username}&format=json`;

  try {
    const response = await axios.get(url); // node will wait for the response before continuing
    const json = response.data;
  
    if (json == undefined || json.Licenses == undefined || json.Licenses.License == undefined) {
      if (err) {
        console.log(err);
      }
      console.log('error1');
      res.redirect(`/profile/${id}`);
    } else {
      const data = json.Licenses;
      const data2 = data.License;
      const lic = [];

      for (var i = 0; i < data2.length; i++) {
        var lic = data2[i];
      }

      res.render('profile/index', {
        user: foundUser,
        json: lic,
        current: page,
        pages: Math.ceil(count / perPage),
        logCount: count,
      });
    };
  } catch (error) {
    console.log(error);
    res.redirect(`/profile/${id}`);
  }
}

router.get('/:id', middleware.isLoggedIn, (req, res) => {
  var perPage = 9
  var page = req.params.page || 1

  User.findById(req.params.id)
    .populate({
      path: 'log',
      options: {
        sort: { date: -1 },
        limit: 8,
        skip: (perPage * page) - perPage
      },
    })
    .exec((err, foundUser) => {
      if (err) {
        req.flash('error', 'Something went wrong. User not found.');
        res.redirect('back');
      } else {
        Logbook.find({ author: req.user.id }).countDocuments().exec((err, count) => {
          if (err) return next(err)
          searchLicenses(foundUser.username)
        });
      }
    });
}

Related