Andrew K. Andrew K. - 3 months ago 11
Node.js Question

Variables not being updated in node.js asynchronously

I'm new to node.js and I have some code that isn't working properly. I think the issue is in asynchronous functions. This code is pretty simple. Read some xml, assign the values to variables, assign those variables as properties that are used to connect to a database in another node.js file. Problem is the variables don't update after reading the xml.

Here's the code,

//set some variables
userXML = "bgdf";
passwordXML = "";
serverXML = "";
databaseXML = "";

//parse the xml
var fs = require('fs'),
xml2js = require('xml2js');
var parser = new xml2js.Parser({explicitArray : false});
fs.readFile(__dirname + '/variables.xml', function(err, data) {
parser.parseString(data, function (err, result) {
userXML = result.variables.user;
passwordXML = result.variables.password;
serverXML = result.variables.server;
databaseXML = result.variables.database;

//What's in this variables? The right values!
console.log(userXML);
console.log(passwordXML);
console.log(serverXML);
console.log(databaseXML);

})
});

exports.dev = {
db: {
//What's in these variables? The wrong values! Values from top of file - never updated
user: userXML,
password: passwordXML,
server: "myservername.net",
database: databaseXML
}
};


I tried adding a .then() promise after the readFile but then my other file is saying that "dev" is undefined.

Answer

Loading configuration files is probably the best use-case for blocking file I/O in node (IMHO). Just use fs.readfileSync() instead.

Otherwise, if you must keep async file reading (which I doubt is the case, when you're trying to load your configuration values for startup), don't try exporting the values directly. Instead, export a function which will provide those values to either a callback or a promise, then use that function instead. You can add some sort of caching mechanism if you need these config values in multiple locations and you want to make sure the file is only read once.

Truth be told (and I'm not sure if this is an option for you), the simplest solution would be ditch the idea of a configuration file altogether, and then to provide the configuration you are looking for (user, server, password, etc) with environment variables, and then reading them from process.env.