NodeJS EventEmitter not being called in event in a class - javascript

When I Register an function as an event, the emit inside said function does not get called. The function it self is called (as tested by log). Now when I register the event using method 2, it works. Why is this?
Method 1 (Does not call event):
"use strict";
const EventEmitter = require("events");
class DiscordBot extends EventEmitter{
constructor(key){
super();
}
startBot(){
var self = this;
this.bot.on("ready",self.botReady);
}
botReady(){
var self = this;
self.emit("Bot_Ready");
console.log("TESD");
}
}
Method 2 (works):
"use strict";
const EventEmitter = require("events");
class DiscordBot extends EventEmitter{
constructor(key){
super();
}
startBot(){
var self = this;
this.bot.on("ready",function () {
self.botReady();
});
}
botReady(){
var self = this;
self.emit("Bot_Ready");
console.log("TESD");
}
}
Register:
bot.on("Bot_Ready", function(){
console.log('this happens ');
});

This creates a closure:
this.bot.on("ready",function () {
self.botReady();
});
Method 1 doesn't:
startBot(){
var self = this;
this.bot.on("ready",self.botReady);
}
From the MDN link above:
A closure is a special kind of object that combines two things: a
function, and the environment in which that function was created. The
environment consists of any local variables that were in-scope at the
time that the closure was created.
Here is another great link that might help explain:
How do JavaScript closures work?
Note this part:
In JavaScript, if you use the function keyword inside another
function, you are creating a closure.

"Maybe you lose context and you need to use arrow function like this this.bot.on("ready", () => this.botReady());" - #yurzui
Works like a charm.

Related

Real inheritance in JavaScript

I tried to implement prototypical inheritance between two AngularJS services and one generic service, but this seems not enough to serve my needs.
I made ChildService, SecondChildService and ParentService.
ChildService extends ParentService with prototypical inheritance
SecondChildService extends ParentService with prototypical inheritance
ParentService has a method let's call it logIt() that logs property it
ChildService implements its own version of it
SecondChildService implements its own version of it
Now I consider ParentService as the "base class", and I have a method within ParentService that calls logIt(), that is initialize(). This is only implemented in ParentService
I need to run ChildService.initialize() and see that the it of ChildService gets logged.
The same thing with SecondChildService.
Instead the ParentService logs its own version of it. The reason I believe is that prototypical inheritance is a composition implementation rather than real inheritance
Can you please propose a workaround?
Edit:
This is my parent service
angular.module('common').service('parentService', ParentService);
ParentService.$inject = [];
/* #ngInject */
function ParentService() {
'use strict';
var vm = this;
vm.it = "parent";
vm.initialize = function () {
vm.logIt();
};
vm.logIt = function () {
console.log(this.it);
};
}
This is my child service
angular.module('common').service('childService', ChildService);
ChildService.$inject = ['parentService'];
/* #ngInject */
function ChildService(parentService) {
'use strict';
var vm = this;
angular.extend(this, parentService);
vm.it = "child";
}
And this is what I get in the log when I run childService.initialize()
parent
I am expecting to get child instead
I can't reproduce your problem. Inheritance seems to work correctly in the following example:
class Main {
do_it() {
console.log("Main do_it");
this.it();
}
it() {
console.log("Main it executed");
}
}
class A extends Main {
it() {
console.log("A it executed");
}
}
var a = new A;
a.do_it();
console.log("Done");
The do_it method that is defined in the Main class correctly calls the it method of the extended class which has overridden the it method of the parent class.
The problem is in ParentService. I am using vm.logIt, while I should be using this.logIt in order to get the it from the child service scope. Contrary to standard inheritance, it seems that in prototypical inheritance the logIt() function exists twice, once in the ParentService and once in the ChildService (inherited from parent). With this.logIt() you can call it from the child and it actually gets the it from the child, while with vm.logIt() you call it from the parent where it gets the it from. It is a matter of scope.
This is the correct implementation of ParentService:
angular.module('common').service('parentService', ParentService);
ParentService.$inject = [];
/* #ngInject */
function ParentService() {
'use strict';
var vm = this;
vm.it = "parent";
vm.initialize = function () {
this.logIt(); // <-- this changed
};
vm.logIt = function () {
console.log(this.it);
};
}

Pass function to javascript class

On my index.html, I have this code,
$(document).ready(function() {
var self = this;
var submit = function() {
alert("Test");
}
const form = new Form(self.submit);
})
In my Form.js, I have this code,
class Form() {
constructor(func) {
var self = this;
// ...
$("submitBtn").click(function(e) {
e.preventDefault();
self.func();
});
// ...
}
}
Why my function is not executing after the submitBtn is clicked?
I used self to get the "this" value. I cant use "new Form(self.submit())" because It will execute the function once the line is read.
Your submit function is a local variable, not a property of this. Thus you need:
const form = new Form(submit);
Similarly, in your constructor, func doesn't have anything to do with self; it should just be
func();
Pointy answers the question. I just want to add that constructor is a place where you usually declare and initialize instance properties, and it's better to register click event in a class method, something like:
class Form{
constructor(){}
click(func){
$("submitBtn").click((e)=>{
e.preventDefault();
func();
});
}
}
Also you dont need to cache the scope var self = this as long as you use arrow function. This answer could be useful Advantages of using prototype, vs defining methods straight in the constructor?

Difference between javascript constructors

I'm having a bit of confusion over which (if any) of these javascript initializes to use, as from what I can tel, they all do the same thing. Are there cases in which I should use one or he other? Mt project requires me to encapsulate several functions and namespaces in a single object so that we don't clutter te global scope with variable names, put I'm especially unclear as to the difference between +function(){}(); and (function())();
Any help would be greatly appreciated. Keep in mind the end goal is for all of our function to be encapsulated in a single namespace. IE MyCompany.function, MyCompany.Namepsace.Function ...
<script>
var Ford = {};
+function() {
Ford.start = function() {
console.log("Ford just started");
};
}();
Ford.start();
</script>
<script>
var Honda = {};
(function() {
Honda.start = function() {
console.log("Honda just srtarted");
};
})();
Honda.start();
</script>
<script>
var Toyota = function() {
return {
start: function() {
console.log("Toyota just strted");
}
};
}
var car = new Toyota();
car.start();
</script>
Javascript functions are only invoked as constructors when the new keyword is used. new creates a new object instance, inherits from the constructor's prototype, and makes the context of the this keyword the newly created object instance. So if you're not using the prototype to inherit properties or the keyword this to create new properties in the constructor--you don't really need to use a constructor.
I think what you're looking for is the module pattern which is implemented using immediately invoked functions. Both of your first two examples use immediately invoked functions. I believe the style (function(){}()); is preferred to +function(){}();. Both the surrounding () and the + cause the javascript parser to expect a function expression rather than a function declaration and this allows the trailing () to invoke the function. Besides being somewhat less readable + may also alter the return value of the function.
I think you want some variation on this (copied from link):
var MODULE = (function () {
var module = {};
var privateVariable = 1;
function privateMethod() {
// ...
}
module.moduleProperty = 1;
module.moduleMethod = function () {
// ...
};
return module;
}());
While all of that is valid JS, you're making assumptions that lead me to believe you may not understand how JS works. The first two example are not constructors in the usual sense at all...they're sort of module pattern, but not even. you could condense it to
var Honda = {};
Honda.start = function() { console.log("Honda just started"); }
and forget the self-executing function. What is shown above is similar to what you'd think of as a static function in other languages:
public class Honda {
public static void start() { Console.WriteLine("Honda Just Started"); }
}
If you wanted an instance function, you need to either attach to the prototype, or to the this keyword in the constructor:
Prototype:
var Honda = function() {}
Honda.prototype.start = function() { console.log("Honda just started"); }
This:
var Honda = function() {
this.start = function(){
console.log("Honda just started");
}
}
Your final example, with Toyota indicates you have a fundamental misunderstanding of how function constructors work. Your object has been discarded, and in return you get some object literal which could have been written:
var Toyota = {
start: function(){
console.log("Toyota just started");
}
}
What you (probably) intend is the "this" pattern I explained on the Honda example above:
var Toyota = function() {
this.start = function() {
console.log("Toyota just started");
}
}
Finally, when writing "namespaced" libraries of functions, the module pattern may be your best friend. This lets you maintain private state without the need for a formal constructor/prototypes, etc:
var MyCompany = {};
//car module
(function(ns){
var module,
_isStarted;
function start() { console.log('start'); _isStarted = true; }
function stop() { console.log('stop'); _isStarted = false; }
function isStarted() { return _isStarted; }
module = {
start: start,
stop: stop,
isStarted: isStarted
}
ns.CarModule = module;
}(MyCompany));
//use:
MyCompany.CarModule.start();
if(MyCompany.CarModule.isStarted()) { MyCompany.CarModule.stop(); }

Is it possible to let Angularjs work with prototype methods and variables

You know, in angularjs, most of logical are based on $scope:
function Ctrl($scope) {
$scope.name = "Freewind";
$scope.hello = function() {
alert($scope.name);
}
$scope.method1 = function() {}
$scope.method2 = function() {}
$scope.method3 = function() {}
$scope.method4 = function() {}
$scope.method5 = function() {}
}
Now I'm using haxe to generate angularjs code, it works if my code is:
class Ctrl {
public function new(scope:Scope) {
scope.name = "Freewind";
scope.hello = function() {
alert(scope.name);
}
scope.method1 = function() {}
scope.method2 = function() {}
scope.method3 = function() {}
scope.method4 = function() {}
scope.method5 = function() {}
}
}
typedef Scope = {
name:String,
hello:Void->Void,
method1: Void->Void,
method2: Void->Void,
method3: Void->Void,
method4: Void->Void,
method5: Void->Void
}
But I want to be benefited from haxe's class system(the code may be simpler and clearer), to declare it like:
class Scope {
public var name:String;
public function hello() {}
public function method1() {}
public function method2() {}
public function method3() {}
public function method4() {}
public function method5() {}
}
Then find a way to associate the Scope class with the $scope of angularjs.
But the generated Scope from haxe are using prototypes:
Scope = function();
Scope.prototype.name = "something";
Scope.prototype.hello = function() {}
Scope.prototype.method1 = function() {}
Scope.prototype.method2 = function() {}
Scope.prototype.method3 = function() {}
Scope.prototype.method4 = function() {}
Scope.prototype.method5 = function() {}
In this case, I can't find a solution to let angularjs work with it.
Is it possible to let angularjs to work with prototypes, so it can work with haxe class system (also other languages like coffeescript/typescript which have class support)?
For the sake of having an actual answer to this question, one should mention that now this library solves the problem: https://github.com/freewind/HaxeAngularSupport ;)
Scope's constructor is declared within a closure, so you don't have easy access to it... BUT(!) JavaScript has the constructor available to you right off of any existing object.
Theoretically, you could get the $rootScope's constructor, alter it's prototype, and that should alter any subsequently created Scopes. You'd probably want to do this in the .run() or .config() on your application module, however.
app.run(function($rootScope) {
$rootScope.constructor.prototype.foo = 'Set from prototype';
});
It works and here's the plunker.
HOWEVER: You probably don't need to do this. The only reason I could think of that you might need to do this is in some edge-case where you needed to make sure some function or property was available on a scope, even if it was an isolated scope (as was the one in the directive in the plunker I linked).
Because there is scope inheritance, and because you have $rootScope to use, I can't really think of any valid reason to need to alter Scope via prototyping.

Anonymous class with MooTools

Can I create the anonymous class(java term) using the MooTools js framework?
Suppose it should look like:
A = new Class({
invoke: function() {
alert('class');
}
});
a = new A({
invoke: function() {
this.parent();
alert('instance');
},
});
But I don't want to modify constructor interface around to accept additional properties.
Is there more comfortable way to define classes that are used not more than once?
You could define the class only within the scope it is going to be used in, which means the class won't be available outside that scope. For example, using a self-executing function:
(function() {
var MyClass = new Class({
invoke: function() {
alert('class');
}
});
var myObject = new MyClass({
invoke: function() {
this.parent();
alert('instance');
}
});
})();
(I've fixed up several errors in your code, including omitting the var keyword when declaring MyClass and myObject, and an extra , when initialising myObject.)

Categories

Resources