0

Currently working on an application that does quite a bit of database work, and thought that one smart way of getting around this should be to use events. So I set up a events emitter for the application to use, and then using this as a way to control the flow. And I kind of assumed that the events emitter would work similar to a message queue or similar.

This was not the case, and for some reason I can not get the even emitter to work as expected on the second call to the same function.

I would have understood if the problem would be that it called multiple times, but as it is, the below code will run the second function twice, but will only get passed the dbEvents.once('Ready' once. And not only can I not figure out why, it seems to work like this constantly, and will never print out "Wrote Fourth"

var mongo = require('mongodb');
var events = require('events');
var dbEvents = new events.EventEmitter();




function writeStuff(first, second, status, cuID){
        console.log('Wrote '+ first);
        if (status === 1) {
            console.log('\t\tReady for '+ cuID);
            dbEvents.emit('Ready');
        } else {
            console.log('\t\tReady (but not 1) for ' + cuID);
            dbEvents.emit('Ready');
        }
        console.log('\t\tjust about to kick of number ' + status);
        dbEvents.once('Ready', function (condata) {
            console.log('Wrote '+ second)
            dbEvents.emit('Done'+cuID)

        });

}

var cuID1 = mongo.ObjectID();
writeStuff('First', 'Second', 1, cuID1);
dbEvents.on('Done'+cuID1, function(){
    console.log('\tFirst completed ' + cuID1);
});

var cuID2 = mongo.ObjectID();
writeStuff('Third', 'Forth', 2, cuID2);

dbEvents.on('Done'+cuID2, function(){
    console.log("\tSecond completed " + cuID2)
});

var b = 0;
for(var i = 0; i < 100000000; i++){
    b++;
}
console.log("And I counted to " + b);

The output when I run the above code looks like this

Wrote First
                Ready for 5540c57cd8fa9555076f9aba
                just about to kick of number 1
Wrote Third
                Ready (but not 1) for 5540c57cd8fa9555076f9abb
Wrote Second
        First completed 5540c57cd8fa9555076f9aba
                just about to kick of number 2
And I counted to 100000000

================ UPDATE ==============

Why can't I generate an event, I.E. if I use a unique identifier it does not seem like I can send it as an event.In this case I change the event to be Ready+cuID (mongodb), and now the second write never gets called.

var mongo = require('mongodb');
var events = require('events');
var dbEvents = new events.EventEmitter();




function writeStuff(first, second, status, cuID){
        console.log('Wrote '+ first);
        if (status === 1) {
            console.log('\t\tReady for '+ cuID);
            var flag = 'Ready'+cuID
            dbEvents.emit(flag);
        } else {
            console.log('\t\tReady (but not 1) for ' + cuID);
            dbEvents.emit('Ready');
        }
        console.log('\t\tjust about to kick of number ' + status);
        dbEvents.once(flag, function (condata) {
            console.log('Wrote '+ second)
            dbEvents.emit('Done'+cuID)

        });

}

var cuID1 = mongo.ObjectID();
writeStuff('First', 'Second', 1, cuID1);
dbEvents.on('Done'+cuID1, function(){
    console.log('\tFirst completed ' + cuID1);
});

var cuID2 = mongo.ObjectID();
writeStuff('Third', 'Forth', 2, cuID2);

dbEvents.on('Done'+cuID2, function(){
    console.log("\tSecond completed " + cuID2)
});

var b = 0;
for(var i = 0; i < 1000000000; i++){
    b++;
}
console.log("And I counted to " + b);
Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
vrghost
  • 1,084
  • 2
  • 19
  • 42

1 Answers1

1

It seems that you're adding the 'Ready' listener after dispatching the 'Ready' event on the first run. Now when you fire of the second run, the first listener will be called. This explains why 'Wrote Second' is logged after 'Wrote Third' is called.

Move the addition of the listener to the beginning of writeStuff().

function writeStuff(first, second, status, cuID){

    console.log('\t\tjust about to kick of number ' + status);
    dbEvents.once('Ready', function (condata) {
        console.log('Wrote '+ second)
        dbEvents.emit('Done'+cuID)

    });

    console.log('Wrote '+ first);
    if (status === 1) {
        console.log('\t\tReady for '+ cuID);
        dbEvents.emit('Ready');
    } else {
        console.log('\t\tReady (but not 1) for ' + cuID);
        dbEvents.emit('Ready');
    }

}
Edo
  • 3,311
  • 1
  • 24
  • 25
  • Thank you very much edo. This does resolve this issue, but does not help me with the bigger issue where the function is called sequentially, but I still have the issue where the first call does the two steps, the second iteration only calls the first one. – vrghost Apr 29 '15 at 12:56
  • Hey man, I'm not seeing what you are trying to achieve in the updated code example. There are a couple of issues: 1) You seem to be adding the listener to 'flag' after dispatching the 'flag' event (see this answer). 2) What are you trying to achieve with the loop at the end? It seems that you might not understand that all of this code will be run synchronously, that is why your listeners won't get called if they're added **after** you dispatch the event. – Edo Apr 30 '15 at 15:42