0

I'm dipping my hands on nodejs with express on trying to make my first application on this platform. On this code on the image, I am from the post request, I am trying to check if the userData sent to me is already registered. If not it will register the user. To minimize Callback, I am going to use Events to tell me if the functions I call are done. In this case, if checkUser function property on the right of the image, if db found the user, it will emit the userAuthenticated event written on the left. If it's not it will write the user and emit the userRegistered event.

The problem is that the sometimes it works, sometimes it does not. This is my first time writing async functions on node, and I am stumped on how it functions.

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Mr A
  • 1,345
  • 4
  • 22
  • 51
  • Tip: posting code and error text is much better than posting screenshots of said items, especially if someone wants to try to reproduce the issue locally. – mscdex Dec 22 '15 at 05:56

1 Answers1

1

The problem is that you're not removing event handlers after the response is sent. on() keeps event handlers around until they're explicitly removed. So for every connection, new event handlers get added but never removed.

Even if you used .once() instead of .on(), you'd still need to remove the handler for the other event that didn't fire.

IMHO you're better off just using a single callback instead of complicating things with an EventEmitter. For example:

models/authenticate.js:

// ...

exports.checkUser = function(data, cb) {
  UsersDB.findOne({ fbid: data.id }, function(err, doc) {
    if (err)
      return cb(err);
    if (doc === null)
      insertUser(data, cb);
    else
      cb(null, 'Authenticated', doc);
  });
};
var insertUser = exports.insertUser = function(data, cb) {
  var insertData = {
    fbid: data.id
    first_name: data.first_name
    last_name: data.last_name,
    email: data.email,
    created_at: new Date()
  };
  UsersDB.insert(insertData, function(err, doc) {
    if (err)
      return cb(err);
    cb(null, 'Registered', doc);
  });
};

controllers/authenticate.js:

// ...

model.authenticate(req.body, function(err, action, data) {
  if (err)
    return res.json({ error: err });
  res.json({ action: action, userData: data });
});

Also, you can simplify your "check and insert" logic to use MongoDB's "upsert" functionality that will perform both steps for you instead of having two separate database calls. To see how to do this, look at this SO answer.

Community
  • 1
  • 1
mscdex
  • 104,356
  • 15
  • 192
  • 153
  • I manage to solve this by using res.end() instead of res.json() but yours is also a good choice. I'm also in the fence of making it a promise instead. But since the code is simple for now, it appears to be the right choice. – Mr A Dec 22 '15 at 06:35