On Wednesday, May 3, 2017 at 11:55:59 PM UTC+2, Peter B. wrote:
>
>
> I need your help. I'm working on a project and I have a problem with the 
> fact that nodejs is asynchronous.
> I want to export my variable called 'macAd'. But even with a global 
> variable, I can't do it. 
>


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.

-- 
Job board: http://jobs.nodejs.org/
New group rules: 
https://gist.github.com/othiym23/9886289#file-moderation-policy-md
Old group rules: 
https://github.com/joyent/node/wiki/Mailing-List-Posting-Guidelines
--- 
You received this message because you are subscribed to the Google Groups 
"nodejs" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit 
https://groups.google.com/d/msgid/nodejs/0fa8243b-3688-4817-bbbe-cb6c5edc5e41%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to