I have an error when trying to inherit EvenEmitter
/* Consumer.js */
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Consumer = function() {};
Consumer.prototype = {
// ... functions ...
findById: function(id) {
this.emit('done', this);
}
};
util.inherits(Consumer, EventEmitter);
module.exports = Consumer;
/* index.js */
var consumer = new Consumer();
consumer.on('done', function(result) {
console.log(result);
}).findById("50ac3d1281abba5454000001");
/* ERROR CODE */
{"code":"InternalError","message":"Object [object Object] has no method 'findById'"}
I've tried almost everything and still dont work
A couple of things. You are overwriting the prototype rather than extending it. Also, move the util.inherits() call before you add the new method:
var EventEmitter = require('events').EventEmitter;
var util = require('util');
var Consumer = function Consumer() {}
util.inherits(Consumer, EventEmitter);
Consumer.prototype.findById = function(id) {
this.emit('done', this);
console.log('found');
};
var c = new Consumer();
c.on('done', function(result) {
console.log(result);
});
c.findById("50ac3d1281abba5454000001");
Related
I'm learning JavaScript/Nodejs and I've decided to start with ES5 before looking at ES6. I'm looking at prototypical inheritance and the EventEmitter.
I want to extend EventEmitter with something simple, my code sample is below. However I receive the error:
this.emit('messageRead', message);
TypeError: this.emit is not a function
What am I doing wrong?
var EventEmitter = require('events').EventEmitter;
var MyEmitter = function() {
EventEmitter.call(this);
this.messages = []
}
MyEmitter.prototype = Object.create(EventEmitter.prototype);
MyEmitter.prototype.constructor = MyEmitter;
MyEmitter.prototype.addMessage = function(message) {
this.messages.push(message)
this.emit('messageAdded', message);
return this;
}
MyEmitter.prototype.readMessages = function() {
this.messages.forEach(function(message){
this.emit('messageRead', message);
});
return this;
}
var emitter1 = new MyEmitter();
emitter1
.addMessage('hello')
.addMessage('goodbye')
.on('messageAdded', function(message) { console.log('message added: ' + message)})
.on('messageRead', function(message) { console.log('message read: ' + message)})
.readMessages();
You must inherit from EventEmitter, not only run constructor in MyEmitter instance scope
const util = require('util');
...
util.inherits(MyEmitter, EventEmitter);
The issue with my code was with this and closures. See the updated readMessages below.
But thanks to #Yarsolav who has probably pointed at a better solution.
var EventEmitter = require('events').EventEmitter;
var MyEmitter = function() {
EventEmitter.call(this);
this.messages = []
}
MyEmitter.prototype = Object.create(EventEmitter.prototype);
MyEmitter.prototype.constructor = MyEmitter;
MyEmitter.prototype.addMessage = function(message) {
this.messages.push(message)
this.emit('messageAdded', message);
return this;
}
MyEmitter.prototype.readMessages = function() {
var that = this;
this.messages.forEach(function(message){
that.emit('messageRead', message);
});
return this;
}
var emitter1 = new MyEmitter();
emitter1
.on('messageAdded', function(message) { console.log('message added: ' + message)})
.on('messageRead', function(message) { console.log('message read: ' + message)})
.addMessage('hello')
.addMessage('goodbye')
.readMessages();
const awsSdk = require('aws-sdk');
module.exports = {
downloadFile(bucketName, fileName, callback) {
var s3 = new awsSdk.S3();
var params = { Bucket: bucketName, Key: fileName };
var file = require('fs').createWriteStream('abcd.jpg');
var stream = s3.getObject(params).on('error', function (err) {
console.log(' download.on');
callback('error', null);
})
.createReadStream()
stream.pipe(file);
}
}
Above, is the code i need to mock in my Test class using proxyquire. The issue is, im not able to mock methods like getObject,on,createReadStream. Also after mocking i need to emit the error event from test class that will trigger the above on method which will call the callback in my test class where exception is tested.
Below is my test class code.
const proxyquire = require('proxyquire').noCallThru().noPreserveCache();
const sinon = require('sinon');
const emitter = require('events').EventEmitter;
function Download() {
emitter.call(this);
this.error = function () {
this.emit('error');
}
}
describe('S3 download test', () => {
awsSdkMock = {}
awsSdkMock.config = {};
awsSdkMock.config.region = { };
var s3Instance = {};
awsSdkMock.S3 = function (){
return s3Instance;
};
var object = {};
s3Instance.getObject = function (params){
return object;
};
var request = {};
const errorCallBack = sinon.spy();
var err = 'error';
object.on = function (err, errorCallBack) {
console.log('object.on');
errorCallBack();
return request;
};
var stream = {};
request.createReadStream = function(){
console.log('createReadStream');
return stream
};
stream.pipe = function(file){
console.log('download.error');
// download.error();
};
Download.prototype.__proto__ = emitter.prototype;
var download = new Download();
const s3 = proxyquire('./../../../modules/s3', {
'aws-sdk': awsSdkMock
})
it('Error in download test', (done) => {
const errorCallBack = sinon.spy();
s3.downloadFile('123', 'abcd', errorCallBack);
sinon.assert.calledWith(errorCallBack, 'error', null);
done();
});
})
Any help is appreciated.
I'm having a small issue, playing around with module patterns. I'm trying to attach an eventemitter to my library, but it doesn't seem to work and I get :
cmd.on('message',function(msg){
^
TypeError: undefined is not a function
My lib looks like :
var util = require('util');
var EventEmitter = require("events").EventEmitter;
var TestLib = function() {
var self = this;
function sendRandom(cb){
self.emit('message','whatever');
cb(null,0);
}
return {
init: function(cb) {
console.log('init');
cb(null);
},
run: function(params,cb){
console.log('running ',params);
sendRandom(function(err,res){
if(err){
cb(new Error(err));
}else{
cb(null,res);
}
});
},
close: function(cb) {}
};
};
util.inherits(TestLib, EventEmitter);
module.exports = TestLib;
And I call it as such :
var cmd = require(__dirname+'/bin/testlib.js')();
cmd.on('message',function(msg){
log(msg);
});
cmd.init(function(err){
if(err){
log(err);
}else{
cmd.run(line,function(err,res){
if(err){
log(err);
}else{
log(res);
}
});
}
});
I'm sure I'm overlooking something simple, but what?
see whether the example below helps you.
testLib.js
var EventEmitter = require('events').EventEmitter;
var util = require('util');
function TestLib(ms) {
var self = this;
EventEmitter.call(this);
this.random = function() {
//emitting 'random' event randomly
var ms = Math.random() * 100000 % 3000;
console.log('emitting random event in ' + ms + ' milliseconds');
setTimeout(function() {
self.emit('random', ms);
self.random();
}, ms);
return self;
}
}
util.inherits(TestLib, EventEmitter);
module.exports = TestLib;
test.js
var TestLib = require('./testLib');
new TestLib()
.random()
.on('random', function(ms) {
console.log('random event emitted after ' + ms + ' milliseconds');
});
to run it, execute node test.js
I am trying to transition from async to promises and this is what I have. If the code looks contrived it's because I simplified it from what I'm working on to make it easier to grasp. I'm struggling to get the Promise.all to execute.
I commented out the async code that I want to implement in promises:
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs-extra'));
var path = require('path');
var tar = require('tar-fs');
module.exports = Archive;
function Archive() {
var self = this;
var self.base_dir = '/bar/baz',
var self.file1 = 'foo/file1',
var self.file2 = 'foo/file2',
var self.file3 = 'foo/file3',
var self.file4 = 'foo/file4'
}
Archive.prototype.make = function(done) {
var self = this;
// async.series([
// function(next) {
// self._prepareFilesDir(next);
// },
// function(next) {
// self._copyFiles(next);
// },
// function(next) {
// self._writeArchive(next);
// }
// ], done)
self._prepareFilesDir().bind(self)
.then(self._copyFiles.bind(self))
.then(self._writeArchive.bind(self))
.catch(function(e) {
return done(e);
});
};
// ********************************
// * Private functions
// ********************************
Archive.prototype._prepareFilesDir = function() {
var self = this;
return fs.emptyDirAsync(self.base_dir);
};
Archive.prototype._copyFiles = function() {
var self = this;
var sources = {
file1: path.resolve('baz', 'file1'),
file2: path.resolve('baz', 'file2')
file3: path.resolve('baz', 'file3')
file4: path.resolve('baz', 'file4')
file5: path.resolve('baz', 'file5')
};
var destinations = {
file1: path.resolve(self.base_dir, self.file1),
file2: path.resolve(self.base_dir, self.file2),
file3: path.resolve(self.base_dir, self.file3),
file4: path.resolve(self.base_dir, self.file4),
file5: path.resolve(self.base_dir, self.file5)
};
var filters = {
qux: /^qux/,
bru: /^bru/,
blerg: /blerg$/
};
function copyFile1() {
console.log('hello world');
return fs.copyAsync(sources.file2, destinations.file1, { filter: filters.qux });
};
function copyFile2() {
return fs.copyAsync(sources.file2, destinations.file2);
};
function copyFile3() {
return fs.copyAsync(sources.file3, destinations.file3, { filter: filters.bru });
};
function copyFile4() {
return fs.copyAsync(sources.file4, destinations.file4, { filter: filters.blerg });
};
return Promise.all([
copyFile1,
copyFile2,
copyFile3,
copyFile4
]);
// async.parallel([
// copyFile1(next),
// copyFile2(next),
// copyFile3(next),
// copyFile4(next)
// ], function(err) {
// if (err) return done(err);
// done(null);
// })
};
Archive.prototype._writeArchive = function() {
var self = this;
var archive_dir_path = path.resolve(self.base_dir, '..');
var tarPromise = function() {
return new Promise(function(resolve, reject) {
tar.pack(self.files_path)
.pipe(fs.createWriteStream(archive_dir_path + '.tar'))
.on('error', reject)
.on('finish', resolve)
});
};
fs.ensureDirAsync(archive_dir_path)
.then(tarPromise);
};
I must be doing something wrong because the 'hello world' is never printed. I think the stream is promisified correctly but I'm not so sure either. I based my conversion on the promise-nuggets.github.io snippets.
How do I have to do the Promise.all? I'd like to keep separate functions as I think it helps understanding the code better.
Thanks,
the mistakes that I found:
in make method, done would be called only in case of error, suggestion remove done callback, just return promise
again in make, you are doing _prepareFilesDir().bind(self), for staters bind at that point is redundant, it should have been call/apply at that point.
in _writeArchive, you need to return promise, else it ll return undefined and assume that the async function is finished.
updated code in fiddle
There were several issues which #mido22 fixed. There is one more issue though, in Pormise.all(), the functions shouldn't be passed as references but rather executed.
var Promise = require('bluebird');
var fs = Promise.promisifyAll(require('fs-extra'));
var path = require('path');
var tar = require('tar-fs');
module.exports = Archive;
function Archive() {
var self = this;
var self.base_dir = '/bar/baz',
var self.file1 = 'foo/file1',
var self.file2 = 'foo/file2',
var self.file3 = 'foo/file3',
var self.file4 = 'foo/file4'
}
Archive.prototype.make = function() { // CHANGED
var self = this;
// async.series([
// function(next) {
// self._prepareFilesDir(next);
// },
// function(next) {
// self._copyFiles(next);
// },
// function(next) {
// self._writeArchive(next);
// }
// ], done)
return self._prepareFilesDir() // CHANGED
.then(self._copyFiles.bind(self))
.then(self._writeArchive.bind(self)); // CHANGED
};
// ********************************
// * Private functions
// ********************************
Archive.prototype._prepareFilesDir = function() {
var self = this;
return fs.emptyDirAsync(self.base_dir);
};
Archive.prototype._copyFiles = function() {
var self = this;
var sources = {
file1: path.resolve('baz', 'file1'),
file2: path.resolve('baz', 'file2')
file3: path.resolve('baz', 'file3')
file4: path.resolve('baz', 'file4')
file5: path.resolve('baz', 'file5')
};
var destinations = {
file1: path.resolve(self.base_dir, self.file1),
file2: path.resolve(self.base_dir, self.file2),
file3: path.resolve(self.base_dir, self.file3),
file4: path.resolve(self.base_dir, self.file4),
file5: path.resolve(self.base_dir, self.file5)
};
var filters = {
qux: /^qux/,
bru: /^bru/,
blerg: /blerg$/
};
function copyFile1() {
console.log('hello world');
return fs.copyAsync(sources.file2, destinations.file1, { filter: filters.qux });
};
function copyFile2() {
return fs.copyAsync(sources.file2, destinations.file2);
};
function copyFile3() {
return fs.copyAsync(sources.file3, destinations.file3, { filter: filters.bru });
};
function copyFile4() {
return fs.copyAsync(sources.file4, destinations.file4, { filter: filters.blerg });
};
return Promise.all([
copyFile1(), // execute functions
copyFile2(), // idem
copyFile3(), // idem
copyFile4() // idem
]);
// async.parallel([
// copyFile1(next),
// copyFile2(next),
// copyFile3(next),
// copyFile4(next)
// ], function(err) {
// if (err) return done(err);
// done(null);
// })
};
Archive.prototype._writeArchive = function() {
var self = this;
var archive_dir_path = path.resolve(self.base_dir, '..');
var tarPromise = function() {
return new Promise(function(resolve, reject) {
tar.pack(self.files_path)
.pipe(fs.createWriteStream(archive_dir_path + '.tar'))
.on('error', reject)
.on('finish', resolve)
});
};
return fs.ensureDirAsync(archive_dir_path)
.then(tarPromise); // CHANGED,
};
I am in process of writing nodejs app. It is based on expressjs. I am confused on doing inheritance in nodejs modules. What i am trying to do is create a model base class, let's say my_model.js.
module.exports = function my_model(){
my_model.fromID = function(){
//do query here
}
}
Now i want to use those methods in my_model in my other model class. let's say user_model.js
How do i inherit my_model in user_model?
in base_model:
function BaseModel() { /* ... */ }
BaseModel.prototype.fromID = function () { /* ... */ };
module.exports = BaseModel;
in user_model:
var BaseModel = require('relative/or/absolute/path/to/base_model');
function UserModel() {
UserModel.super_.apply(this, arguments);
}
UserModel.super_ = BaseModel;
UserModel.prototype = Object.create(BaseModel.prototype, {
constructor: {
value: UserModel,
enumerable: false
}
});
UserModel.prototype.yourFunction = function () { /* ... */ };
module.exports = UserModel;
Instead of using Object.create() directly, you can also use util.inherits, so your user_model becomes:
var BaseModel = require('relative/or/absolute/path/to/base_model'),
util = require('util');
function UserModel() {
BaseModel.apply(this, arguments);
}
util.inherits(UserModel, BaseModel);
UserModel.prototype.yourFunction = function () { /* ... */ };
module.exports = UserModel;
With ES6 the usage of util.inherits() is discouraged in favor of ES6 class and extends
const EventEmitter = require('events');
class MyStream extends EventEmitter {
constructor() {
super();
}
write(data) {
this.emit('data', data);
}
}
const stream = new MyStream();
stream.on('data', (data) => {
console.log(`Received data: "${data}"`);
});
stream.write('With ES6');
Using utility.inherits can also help you decouple the child from the parent.
Instead of calling the parent explicitly, you can use super_ to call the parent.
var BaseModel = require('relative/or/absolute/path/to/base_model'),
util = require('util');
function UserModel() {
this.super_.apply(this, arguments);
}
util.inherits(UserModel, BaseModel);
utility.inherits source:
var inherits = function (ctor, superCtor) {
ctor.super_ = superCtor;
ctor.prototype = Object.create(superCtor.prototype, {
constructor: {
value: ctor,
enumerable: false
}
});
};