0

So here is the module:

module.exports = function(word) {
  fb.once('value', function(snapshot) {
      var data = snapshot.val();
      data.forEach(function(dataSnap) {
          var index = word.indexOf(' ');
          var first = dataSnap.Name.substring(0, index);
          var last = word.substring(index + 1);
          var candidate = dataSnap.Name;
          if (candidate.indexOf(first) >= 0 && candidate.indexOf(last) >= 0)
            return dataSnap.CID;
      });
  });
}

And here is sample code to use the module:

var nameDB = require('./fire.js');
console.log(nameDB('John Doe'));

If I were to do console.log of the module, it returns the intended result however when I make it a module and call it from another file it returns undefined. I realize the module call happens before the function completely runs. How would I fix this?

najm
  • 834
  • 1
  • 13
  • 32
  • 2
    There is nothing to *fix* here. Firebase loads data asynchronously, like most operation in node.js. Instead of trying to make it synchronous, you should design your module around the asynchronous nature. One way to do that is with promises, like Datsik's answer describes. The alternative is to work with callbacks. See for example this answer: http://stackoverflow.com/questions/26297654/passing-variable-in-parent-scope-to-callback-function/26299662#26299662 – Frank van Puffelen Jun 06 '15 at 02:49
  • 1
    Yup, that's one way to fix it. Great to see that you found it! Datsik's approach with promises is a more modern alternative to using callbacks (see a.o. http://www.html5rocks.com/en/tutorials/es6/promises/). I provided a link to a longer explanation that uses callbacks in a comment above and marked your question as a duplicate. – Frank van Puffelen Jun 06 '15 at 02:52
  • Thanks once again @FrankvanPuffelen ! You always help me out with any firebase issues. However I do have a question for you which might seem like newbie one like the rest of mine but since I'm using .once() and checking for values, my main objective is to just check it once and if that user exists then return their CID. How would I _close_ that specific firebase process once it returns me the CID? – najm Jun 06 '15 at 02:58
  • In node.js? `process.exit()` normally does the trick. :-) More seriously: you might see if `goOffline()` exits the process too. But in general I hardly ever have a need to forcefully exit a node.js process after a single operation. If you have that need, you might want to reconsider your approach. – Frank van Puffelen Jun 06 '15 at 04:18
  • Yep `process.exit()` worked as I was intending it to however I modified the code so that I no longer have the need for it. Thanks again! – najm Jun 06 '15 at 18:46

2 Answers2

3

You could simply implement a Javascript promise into your file like so:

module.exports = function(word) {
  return new Promise(function(resolve, reject) { 
      fb.once('value', function(snapshot) {
          var data = snapshot.val();
          data.forEach(function(dataSnap) {
              var index = word.indexOf(' ');
              var first = dataSnap.Name.substring(0, index);
              var last = word.substring(index + 1);
              var candidate = dataSnap.Name;
              if (candidate.indexOf(first) >= 0 && candidate.indexOf(last) >= 0)
                resolve(dataSnap.CID);
              else
                reject('Some sort of failure')
          });
      });
  });
}

Then in your file when requiring it

var nameDB = require('./fire.js');

nameDB('John Doe')
.then(function(data) {
   console.log(data);
});

The nice thing about promises like this, is you can return a new promise and just keep the .then train going like so:

nameDB('John Doe')
.then(function(data) {
   console.log(data);
   return nameDB('Paul Walker');
})
.then(function(data) {
   console.log(data);
   return nameDB('Big Mike and The Boys');
})
.then(function(data) {
   console.log(data);
})
.catch(function(err) {
   console.log(err);
});
Datsik
  • 14,453
  • 14
  • 80
  • 121
  • The concept of Promise(s) is new to me so I copied the code you provided however it still did not show anything in the console. – najm Jun 06 '15 at 02:40
  • @NajmSheikh I'm not sure if you can use Promises in node.js, you might have to use io.js (it's basically Node.js but with implemented ES6 features it's really easy to use, just replace Node with it) – Datsik Jun 06 '15 at 04:05
-1

The user @copy suggested to me on the Javascript chatroom at StackOverflow to use a callback. Using a callback seemed to have fixed the issue for me. The new code looks like:

module.exports = function(word, callback) {
  fb.once('value', function(snapshot) {
    var data = snapshot.val();
    data.forEach(function(dataSnap) {
        var index = word.indexOf(' ');
        var first = dataSnap.Name.substring(0, index);
        var last = word.substring(index + 1);
        var candidate = dataSnap.Name;
        if (candidate.indexOf(first) >= 0 && candidate.indexOf(last) >= 0)
          callback(dataSnap.CID);
    });
  });
}

and for the other file:

nameDB('John Doe' , function(word){
  console.log(word);
});
najm
  • 834
  • 1
  • 13
  • 32