If I understood correctly, you want to export macAd? But later you don't see this variable? Well, it might take a few words to explain, but it's a simple thing really.
The problem is if you do something like:
let macAd; // undefined
module.exports = macAd; // again, undefined
macAd = 3; // doesn't matter now, because the exports is bound to undefined already
if you require it later, you'll get undefined, not a reference to your variable. It's passed by value.
But if you export an object instead, you can modify that object later (say, by setting a macAd property), without changing the reference to the object - which means whoever required the module will get to resolve the value after you set it.
Have your module set up like this:
const macAd = require('macad')
const obj = {
macAd: undefined,
};
module.exports = obj;
// Now the export has a firm grip on our object. EVen if the value is undefined itself, the object is there and it'll be
// useful later.
console.log(obj); // -> { macAd: undefined };
macAd.getMac(function (err, mac) {
// obviously handle error first.
obj.macAd = mac;
console.log(obj); // -> { macAd: '::1' };
});
Then, when you require the module later, at first it's going to be undefined, but later it should resolve to your value. E.g.
const myModule = require('./whatever-you-named-it');
const TIMEOUT = 1000; // or however long the 'macad' module takes.
console.log(myModule.macAd); // -> undefined
setTimeout(function () {
console.log(myModule.macAd); // -> should give you ::1 or something.
}, TIMEOUT);
Now you have a problem though, your module is async, but you're not sure when is it complete and when it's safe to use it. That TIMEOUT might be either too much for you or maybe too short if the computer is busy.
You can get around that by wrapping the getMac call in an initializer function, like this:
const macAd = require('macad')
const obj = {
macAd: undefined,
initialize: function () {
// I use a promise but yuou can go with a callback too
return new Promise(function(resolve, reject) {
macAd.getMac(function (err, mac) {
if (err) {
return reject(err);
obj.macAd = mac;
resolve();
});
});
}
};
module.exports = obj;
console.log(obj); // { macAd: undefined, initialize: [Function] }
Now you can require a module, and call initialize on it, and you'll get a promise resolved (or rejected) when the macAd is available, like this:
const myModule = require('myModule');
console.log(myModule.macAd); // most likely undefined
myModule.initialize()
.then(function() {
// now myModule.macAd is available.
console.log(myModule.macAd); // ::1
})
.catch(console.error);
But here we have other issues. For one, you might simply call getMac directly elsewhere like this, there's no direct benefit in wrapping it in its own module. And another thing - every time you call your module, the getMac is going to be resolving. In this particular case it might not be a big issue, but what if it wasn't a getMac? What if it was something calling an expensive 3rd party service? You call it every time you call this.
That's why you basically store a reference to that promise, and only call the full init once - every other time you return what you already have.
const macAd = require('macad')
let initPromise; // by keeping it out of obj, you're keeping it private to the module itself.
const obj = {
macAd: undefined,
initialize: function () {
// first check if another module already called init - then just resolve what we have, they don't have to wait for getMac
if (initPromise) {
return initPromise;
}
// if it wasn't already called, call macAd now and store the resulting promise in initPromise.
initPromise = new Promise(function (resolve, reject) {
macAd.getMac(function (err, mac) {
if (err) {
return reject(err);
}
obj.macAd = mac;
});
});
return initPromise;
}
};
module.exports = obj;
Hope this helps you out a bit.