Node event emitter in other modules - javascript

I have 3 different javascript files, the smallest one is emitting an event, meanwhile the second (bigger one) file picks up the event and sends it further to the main file.
This is what I have tried so far:
//mini.js
var EventEmitter = require('events').EventEmitter;
var ee = new EventEmitter;
console.log("Emitting event");
var message = "Hello world";
ee.emit('testing',message);
//second.js
var mini = require('./mini.js');
var EventEmitter = require('events').EventEmitter;
var ee = new EventEmitter;
mini.on('testing',function(message){
console.log("Second file received a message:",message);
console.log("Passing further");
ee.emit('testing',message);
});
//main.js
var sec = require('./second.js');
sec.on('testing',function(message){
console.log("Main file received the message",message);
});
However, I get
mini.on('testing',function(message){
^
TypeError: undefined is not a function
error when executing the file with node.
What am I doing wrong here?
Thanks

You're not exporting your EventEmitter instance in mini.js. Add this to mini.js:
module.exports = ee;
You'll also need to add a similar line in second.js if you want to export its EventEmitter instance in order to make it available to main.js.
Another problem you'll run into is that you're emitting testing in mini.js before second.js adds its testing event handler, so it will end up missing that event.

This one should work :
This is the content to put inside first.js :
//first.js
var util = require('util'),
EventEmitter = require('events');
function First () {
EventEmitter.call(this)
}
util.inherits(First, EventEmitter);
First.prototype.sendMessage = function (msg) {
this.emit('message', {msg:msg});
};
module.exports = First;
This is the content to put inside second.js :
//second.js
var First = require('./first.js');
var firstEvents = new First();
// listen for the 'message event from first.js'
firstEvents.on('message',function(data){
console.log('recieved data from first.js is : ',data);
});
// to emit message from inside first.js
firstEvents.sendMessage('first message from first.js');
Now run node second.js and you should have the 'message' event fired for you.
You can use this pattern to achieve any level of messaging between modules.
Hope this helps.

Related

Single instance of an object from a file in javascript

This is creating 3 socket connections. There needs to be only 1 socket connection. This is probably fundamental javascript, but I am unable to figure out how to access the same instance of an object multiple times.
// File: socketConnection.js
// -----------------------------------
let socket = {};
const socketConnection = {};
socketConnection.connect = function() {
if (!socket.connected) {
socket = socketio();
}
};
export default socketConnection;
// File1
// -----------------------------------
import socketConnection from '../../socket/socketConnection';
socketConnection.connect();
// File2
// -----------------------------------
import socketConnection from '../../socket/socketConnection';
socketConnection.connect();
// File3
// -----------------------------------
import socketConnection from '../../socket/socketConnection';
socketConnection.connect();
There are good reasons why it needs to be called from 3 separate files. But how can I ensure that there is only one socket that is referred to when checking !socket.connected ?
Is it possible that your three calls are all executing so quickly that the socket created in the first call hasn't had a chance to connect yet? You may just be overwriting the socket 3 times. If so, you could change your code to rely instead on whether the socket object has been created instead of its connection status. Something like this:
// File: socketConnection.js
// -----------------------------------
let socket;
const socketConnection = {};
socketConnection.connect = function() {
if (!socket) {
socket = socketio();
}
return socket;
};
export default socketConnection;

How to add DockerEvents to my Javascript

I'm using Dockerode and now I want to implement a listener so I have founded docker-events but when I want to use it I got this error :
ReferenceError: DockerEvents is not defined
My code look like this :
if (Meteor.isServer) {
//publish the collection
Meteor.publish('infosContainers', function readInfosContainers() {
return InfosContainers.find({});
});
}
Meteor.startup(() => {
console.log("startup server");
//at the start I create the docker object
docker = new Docker({socketPath: '/var/run/docker.sock'});
//create the docker events
emitter = new DockerEvents({
docker: new Dockerode(docker),
});
//maybe I need to create it like this
emitter = new DockerEvents(docker);
//start the emitter
emitter.start();
});
/**
* this method listen if a container Start
**/
emitter.on("start", function(message) {
console.log("container started: %j", message);
});
Someone know what I'm doing wrong ? Thank you for the help
The error means that you are trying to access a variable that doesn't exist, i.e. you don't have var DockerEvents = ...; anywhere.
I assume you load dockerode like this:
var Docker = require('dockerode');
If you want to use docker-events, you have to do the same:
var DockerEvents = require('docker-events');
require('modulename') is how you load modules in Node.js.
How to use docker-event is already described in its documentation:
var emitter = new DockerEvents({
docker: docker, // since you defined docker earlier
});

Mongoose possible issue

I have an issue using mongoose.
The application I am writing consists in a file watcher that notifies clients about certain events via email and socketio messages.
I made an example that shows the problem:
basically, there is a class called mainFileWatcher that contains a submodule which in turn watches for new files or folders created in the script directory, emitting an "event" event when that happens. The mainFileWatcher listens for that event and calls a static method of a mongoose Client model.
If you run the script setting REPL=true you'll be able to access a watcher.submodule object and manually emit an "event" event.
Now, if you manually trigger the event, you'll see a statement that
says that the "event" event was triggered and an email address as a response.
Otherwhise, if you create a file or a folder in the script folder, you'll
just see that statement. Actually, if you run the script with REPL=true
you'll get the email only after pressing any key, nothing otherwise.
The fact that you don't get the email address as a response means to me that
the code in the promise in mongoose model doesn't get called for some reason.
Here is the code, sorry I couldn't make it shorter
// run
// npm install mongoose bluebird inotify underscore
//
// If you run the script with REPL=true you get an interactive version
// that has as context the filewatcher that emit events in my original code.
// It can be acessed through the watcher.submodule object.
// The watcher triggers a "event" event when you create a file or a folder in the script
// directory.
//
// If you emit manually an "event" event with the watcher.submodule in the repl, you should see a
// statement that "event" was triggered and
// an email address (that belongs to a fake client created by the bootstrap
// function at startup).
// If instead you create a file or a folder in the script folder (or whatever folder you have setted),
// you should see this time you'll have no email response. Actually, if you run with REPL=true,
// you'll have no email response untill you press any key. If you run without REPL, you'll
// have no email response.
'use strict';
var mongoose = require('mongoose');
//mongoose.set('debug', true);
mongoose.Promise = require('bluebird');
var Schema = mongoose.Schema;
var EventEmitter = require('events');
var util = require('util');
var _ = require("underscore");
var Inotify = require('inotify').Inotify;
var inotify = new Inotify();
// Schema declaration
var clientSchema = new Schema({
emails: {
type: [String]
}
}, {strict:false});
clientSchema.statics.findMailSubscriptions = function (subscription, cb) {
this.find({
subscriptions: {$in: [subscription]},
mailNotifications: true
}).exec().then(function (clients) {
if(!clients || clients.length === 0) return cb(null, null);
var emails = [];
clients.forEach(function (client) {
Array.prototype.push.apply(emails, client.emails)
});
return cb(null, emails);
}).catch(function(err){
console.error(err);
})
};
var clientModel = mongoose.model('Client', clientSchema);
// Mongoose connection
mongoose.connect('mongodb://localhost:27017/test', function (err, db) {
if (err) console.error('Mongoose connect error: ', err);
});
mongoose.connection.on('connected', function () {
console.log('Mongoose connected');
});
// bootstrap function: it inserts a fake client in the database
function bootstrap() {
clientModel.findOne({c_id: "testClient"}).then(function (c) {
if(!c) {
var new_c = new clientModel({
"name": "Notifier",
"c_id": "testClient",
"subscriptions": ["orders"],
"registeredTo": "Daniele",
"emails": ["email#example.com"],
"mailNotifications": true
});
new_c.save(function(err){
if (err) console.error('Bootstrap Client Error while saving: ', err.message );
});
}
});
}
// submodule of the main file watcher: it looks for new files created in the script dir
var submoduleOfFileWatcher = function() {
var _this = this;
var handler = function (event) {
var mask = event.mask;
var type = mask & Inotify.IN_ISDIR ? 'directory' : 'file';
if (mask & Inotify.IN_CREATE) {
_this.emit("event", event);
}
}
var watcher = {
path: '.', // here you can change the path to watch if you want
watch_for: Inotify.IN_CREATE,
callback: handler
}
EventEmitter.call(this);
this.in_id = inotify.addWatch(watcher);
}
util.inherits(submoduleOfFileWatcher, EventEmitter);
// Main File Watcher (it contains all the submodules and listensto the events emitted by them)
var mainFileWatcher = function () {
this.start = function() {
bootstrap();
_.bindAll(this, "onEvent");
this.submodule = new submoduleOfFileWatcher();
this.submodule.on("event", this.onEvent)
};
this.onEvent = function() {
console.log("event triggered");
clientModel.findMailSubscriptions("orders", function(err, mails) {
if (err) console.error(err);
console.log(mails); // THIS IS THE CODE THAT OUTPUTS ONLY IF YOU TRIGGER THE "event" EVENT manually
})
}
}
// Instantiate and start the watcher
var watcher = new mainFileWatcher()
watcher.start();
// start the repl if asked
if (process.env.REPL === "true") {
var repl = require('repl');
var replServer = repl.start({
prompt: 'filewatcher via stdin> ',
input: process.stdin,
output: process.stdout
});
replServer.context.watcher = watcher;
}
Just copy and paste the code, install deps and run it.
Things I tried:
I changed the mongoose Promise object to use bluebird promises, hoping that
I could intercept some exception.
I browsed Mongoose calls with node-inspector and indeed the find method gets called and it seems that it throws no exceptions. I really can't figure out what's happening because I don't get any errors at all.
It is not the database connection (I tried to open one just before the findMailSubscriptions call and got an exception for trying to open an already opened connection).
I figure it might be some issues with scopes or promises.
Is there something I am missing about mongoose, or is it just my code that causes this behaviour?

Test context missing in before and after test hook in nightwatch js globals

I have multiple nightwatch tests with setup and teardown in every single test. I am trying to unify it into globalModule.js in before after(path set in globals_path in nightwatch.json).
//globalModule.js
before:function(test, callback){
// do something with test object
}
//sampletest.js
before: function(test){
..
},
'testing':function(test){
....
}
My problem is test context is not available in globalsModule.js. How do i get it there? Can someone let me know?
Test contex not available now. As said beatfactor, it will available soon.
While it not available try use local before first file, but it hack.
Also you can export all your file into one object and export it into nightwatch, but then you can use local before just in time.
For example:
var tests = {};
var befores = [];
var fs =require('fs');
var requireDir = require('require-dir');
var dirs = fs.readdirSync('build');
//if you have dirs that should exclude
var usefull = dirs.filter(function(item){
return !(item=='data')
});
usefull.forEach(function(item){
var dirObj = requireDir('../build/' + item);
for(key in dirObj){
if(dirObj.hasOwnProperty(key))
for(testMethod in dirObj[key])
if(dirObj[key].hasOwnProperty(testMethod))
if(testMethod == 'before')
befores.push(dirObj[key][testMethod]);
else
tests[testMethod] = dirObj[key][testMethod];
}
});
tests.before = function(browser){
//some global before actions here
//...
befores.forEach(function(item){
item.call(tests,browser);
});
};
module.exports = tests;
For more information https://github.com/beatfactor/nightwatch/issues/388

React-Flux: Error with AppDispatcher.register

I am trying to set up the most basic app in Flux-React. Its sole goal to is fire an Action, which gets sent through the Dispatcher to a Store that has registered with the Dispatcher. The store the logs the payload to Console.
Everything besides the Store is working well, but as soon as it hits AppDispatcher.register, Flux throws the following error:
Uncaught TypeError: Cannot set property 'ID_1' of undefined
Here is the code of the file causing the error, but I've put up the entire project at https://github.com/bengrunfeld/react-flux-dispatcher-error, and you can find the offending file in src/js/stores/AppStores.js
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var AppConstants = require('../constants/AppConstants');
var assign = require('object-assign');
var CHANGE_EVENT = 'change';
var AppStore = assign({}, EventEmitter.prototype, {
emitChange: function() {
this.emit(CHANGE_EVENT);
}
});
AppDispatcher.register(function(payload){
console.log(payload);
return true;
})
module.exports = AppStore;
Because of the drought of documentation of biblical proportions for Facebook Flux, I didn't know that I was using code from previous versions.
In AppDispatcher.js, you need to define AppDispatcher in the following way using the new keyword:
var Dispatcher = require('flux').Dispatcher;
var assign = require('object-assign');
var AppDispatcher = assign(new Dispatcher(), {
handleViewAction: function(action) {
this.dispatch({
source: 'VIEW_ACTION',
action: action
});
}
});
module.exports = AppDispatcher;
Here is a link to a repository with the working code: https://github.com/bengrunfeld/react-flux-simple-app

Categories

Resources