vrghost
vrghost

Reputation: 1224

Strange behaviour coding with events

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);

Upvotes: 0

Views: 36

Answers (1)

Edo
Edo

Reputation: 3481

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');
    }

}

Upvotes: 1

Related Questions