express/node, understanding rendering template and asynchronous model

I have some troubles understanding how my application should properly run in terms of loading JSON and rendering template.

Imagine having route dashboard, where I want to gather some data from external API. I have created custom file (tools.js), that I have a function for fetching data from the source written in ( https.request(options, function(res)) {...} ), so basically the process looks like:

  1. I open my route in browser (tools.js is starting to gather JSON from external API)
  2. Template renders, and result of tools.js call is still undefined
  3. tools.js just ended its loading, displays correct data in console, but the template is already rendered with undefined results.

I hope this makes sense. I understand, that this is an expected behaviour, but how can I "re-render" template after getting data from tools.js?

You'll need to do something like this:

tools.js:

var https = require('https');

var options = ...

exports.getData = function(cb) {
  var done = false;
  function errorHandler(err) {
    if (!done) {
      done = true;
      cb(err);
    }
  }
  https.request(options, function(res) {
    var buf = '';
    res.setEncoding('utf8');
    res.on('data', function(d) {
      buf += d;
    }).on('end', function() {
      if (!done) {
        done = true;
        var ret;
        try {
          ret = JSON.parse(buf);
        } catch (ex) {
          return errorHandler(ex);
        }
        cb(null, ret);
      }
    }).on('error', errorHandler);
  }).on('error', errorHandler).end();
};

route:

var getData = require('./tools').getData;

// ...

app.get('/json', function(req, res) {
  getData(function(err, data) {
    if (err) return res.send(500);
    res.render('mytemplate', { jsondata: data });
  });
});

You need to render your template after you've obtained the data. So, you wait for the callback or promise from your async fetching of data and in that callback, once you have the data, you can then render your template.

If you post your code, we could help much more specifically.

Node route handers are designed to be async. They aren't done until you explicitly tell them you're done with the appropriate function call on the response object so they can finish some time later after you're async fetching of data completes, you combine the data with your template and then tell the response object that you're done.