I'm debugging a NodeJS application in Intellij. I have a method that looks as follows:
function(connection) {
connection.on('error', function(error) {
console.log('there is an error'); // breakpoint is on this line
});
}
When the breakpoint is hit, connection is not defined, and putting connection in the Evaluate Expression window yields "ReferenceError: connection is not defined."
It appears to me that connection is being deallocated because it's not being used within the callback, but I'm debugging the application, so how can I make it not be deallocated, short of adding the line localConnection = connection (which does work).
Here's another example:
var foo = (function() {
var a = 'some value';
this.bar = function() {
console.log('bar'); // breakpoint is here
};
this.bar();
})();
Here, a is inaccessible from the debugger.
EDIT:
To clarify the second example, a is private to methods declared outside of foo, but not otherwise. Case in point:
var foo = (function() {
var a = 'Some value';
this.bar = function() {
console.log('a: ' + a); // breakpoint is here
};
this.bar();
})();
This example does print "a: Some value," suggesting that a should be accessible within the line. And as a matter of fact, simply by adding it in the console log, it does stay accessible in that line, which suggests that its previous inaccessibility was due to garbage collection or reference counting, which, in a debugging environment, I would like to be less rigorous, because I would like to maintain the ability to see the values of variables that are not necessarily used in code at debug-time.
The same applies to the first example. When using connection inside the callback in code, it's exposed to the debugger, but I'm trying to make it stay exposed even without code usage. How do I do that? I'm quite positive there is a runtime flag for Node to accomplish that.
First example, connection is an event emitter. so the outer function has already been finished to work when "error" event occurs. So you can not get it back. second example is an IIFE and "a" is somewhat a private variable even if does not look like that way.
You can use a global variable to access both of them. I know this looks like a dirty workaround. but it works anyway, here is an example:
var m;
function(connection) {
m = connection;
connection.on('error', function(error) {
console.log('there is an error'); // breakpoint is on this line
console.log(m); // now you can access connection
});
}
Related
I'm new to nodejs and trying to learn the basics by rebuilding an existing i2c sensor system.
Got it all running using a named functions and async.series inside a single file. To keep make reusable i now want to create a class which i then can import. unfortunatly i get some errors i don't understand.
class.js
const async = require('async');
const i2c = require('i2c-bus');
class Sensor {
constructor (channel) {
this.channel = channel;
var self = this;
}
openBus (callback) {
bus = i2c.open(self.channel, (err) => {callback()}); // shorted for stackoverflow
}
closeBus (callback) {
bus.close( (err) => {callback()}); //also shorted for better readability
}
connection (callback) {
/* first variation */
async.series([openBus, closeBus], callback);
connection2 (callback) {
/* second variation */
async.series([this.openBus, this.closeBus], callback);
}
}
module.exports = K30;
when i import the class, i can without any problem create a new sensor 'object' and call the functions directly using:
> var Sensor = require('./class.js');
> var mySensor = new Sensor(1);
> mySensor.openBus(foo);
> mySensor.closeBus(bar);
but if i go an try call the wrapper-functions, i get the following errors:
> mySensor.connection(foo);
ReferenceError: openBus is not defined (at 'connection')
> mySensor.connection2(foo);
ReferenceError: self is not defined (at 'openBus')
i believe those errors occure due to my lack of understanding the correct usage of this and self. sadly i can't find any good ead on that topic. any help is highly appreciated.
UPDATE
the solution provided in the first two anwsers was in fact my first approch before starting to use "self" (after some googling [this-that-trick]).
anyways, here is the output/error i get using "this.channel" instead:
> mySensor.connection2(foo);
TypeError: Cannot read property 'channel' of undefined (at openBus)
This is not saved anywhere var self = this; and therefore is lost when the function (constructor is function) ends.
Just remove the above line in constructor and use everywhere the this instead of self.
Its true that this keyword is little tricky in javascript, but if you follow reasonable approach, you should be fine.
You indeed have issue with this and self
Every member inside the class has to be referred by this. If you declare a variable named var EBZ-Krisemendt = "SO user";, to access it, you need to use it with this, eg: console.log(this.EBZ-Krisemendt);
What you need here is
openBus (callback) {
bus = i2c.open(this.channel, (err) => {callback()});
}
and then mysensor.connection2(foo) will work fine.
while i still don't fully understand the reason behind this i fixed my code by getting rid of that "ES6" class definition.
class.js
const i2c = require('i2c-bus');
const async = require('async');
function Sensor(channel) {
let that = this; // make 'this' available in sub-function scope
this.channel = channel;
function openBus(cb) {
// open the bus-connection
bus = i2c.open(that.channel);
}
function closeBus(cb) {
// close the bus-connection
}
function connection(cb) {
async.series([openBus, closeBus], cb);
}
function getReading(cb) {
async.until(
function() {
// loop condition e.g. max tries to get reading
},
function(cb) {
connection(cb); // calling nested synchronous connection-routine
},
function (err) {
// result handling
}
); // end async.until
} // end getReading
return {
getReading: getReading
} // make only 'getReading' available
}
module.exports = {
Sensor: Sensor
} // make 'Sensor' available
in the 'member'-functions i can now use the 'class'-variables of 'Sensor' by accessing them with 'that' (e.g.: 'that.channel')
Detail:
function openBus(cb){
bus = i2c.open(that.channel);
}
if i'd use this instead of that it would only work while calling openBus directly. in my example it's neccessary to call openBus and closeBus in a synchronous manner (for obvious reasons). since async.series is additionally nested inside async.until (sensor might need several tries to response) the scope of this changes. by using that instead i'm able to ignore the scope.
Comment:
since the solution is kinda generally pointing to using nested async-calls inside custom modules i'll slightly alter the titel of the initial question. i'm still hoping for better solutions and/or explanations, so i won't mark my own anwser as accepted yet.
My application is a simple mysql client used from command line - it connects to database and makes few queries to get information from database. Mysql functionality is encapsulated in a class and problem is since calls to mysql server is async (understandably) - the code flow reaches end of application.
And I am unable to refer to 'this'(Mysql) inside a method of Mysql class.
How do I get around this problem ?
Below is my code.
//CLASS
function Mysql(config) {
//...
}
//METHOD
Mysql.prototype.getDbInfo = function (cbk) {
this.showTables(function(e,r) {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(this.configVar);
});
}
module.exports = Mysql;
//CLASS OBJECT
var test = new Mysql(config);
//METHOD INVOKE
test.getDbInfo(function (err,results) {
//...
});
Every time that you jump into a callback function you are loosing the scope of the this object. There are different ways to work around it.
Assign this to another variable
The first solution is to assign the this object to another variable (e.g.: that, self). When you assign one variable to another and the first variable is an object then you keep the reference to the original object and you can use it within the callback. Something like that:
Mysql.prototype.getDbInfo = function (cbk) {
var self = this;
self.showTables(function(e,r) {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(self.configVar);
});
}
Bind the this object to the function
You can bind the this object to the function and like that you set the this keyword set to the provided value (in your case the scope outside of showTables function). You can read the documentation of this and you will be able to understand more:
Mysql.prototype.getDbInfo = function (cbk) {
this.showTables(function(e,r) {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(self.configVar);
}.bind(this));
}
Use es6 arrow functions
It is more or less the same solution like the first one. If you use a transpiler you will find out that it is translated like the first solution:
Mysql.prototype.getDbInfo = function (cbk) {
self.showTables((e,r) => {
// >>>>>>>>>> PROBLEM HERE using 'this' <<<<<<<<<<<
console.log(this.configVar);
});
}
NOTE: I edited this question to more accurately show the problem, rather than delete and rewrite it. Hope that's OK.
For the following code:
var Q = require('q');
function first (){
var d = Q.defer();
setTimeout(function(){
d.resolve([]);
}, 1000);
return d.promise;
}
function second(v){
sdf;
console.log("hi")
}
first()
.then(second);
How can I determine that there is a ReferenceError in there? Is the only option to add a second function argument in the then call?
Even though it's not recommended, I tried using process.on('uncaughtException') but to no avail.
Thanks!
Rewrite your final call like this:
function errorHandler(err) {
console.log('You had an error, ' + err);
}
first
.then(second, errorHandler);
The promise captures any exceptions that throw within it, you need to explicitly handle it.
A variation that's q specific would be:
first
.then(second)
.fail(errorHandler);
You may consider this easier to read.
I think it may be appropriate to catch the error before the declaration of the contract object. So something like this:
map(locations, function(loc) {
if(!loc.ClientId) {
console.log("Error: loc.ClientId is undefined");
} else {
var contract = {
"clientName": clients[loc.ClientId][0]
}
...
}
})
Here the error is logged to console when loc.ClientId is undefined.
It really depends what your stack trace looks like. If you're using express or restify, for example, you may actually need to listen for the uncaughtException event on your server object. The error is normally not lost; put something like this into a sample JS file:
null.f();
and you'll see a TypeError thrown, as you are expecting.
If you're not sure of the stack, log it:
console.log(new Error("this is my stack").stack);
I have a worker class that has lots of different utility methods, and emits error messages when there's a problem anywhere in the execution. Due to NodeJS magic, error messages are special, and if nothing is listening to them, they're turned into thrown Errors, so I currently do:
var myWorkerFunction = function(input) {
var w = myFactory();
try {
w.dothis();
w.dothat(input);
w.hokeypokey();
return w.finalize();
} catch(e) {
return false;
}
}
What I wonder though, is it possible to avoid the try/catch block entirely? NodeJS's documentation seems to indicate it's best to avoid not re-throwing a caught exception (I'm doing no checks here to see that it really was my worker's logic that threw the exception and not a critical fault from Node).
So I'd like to do something like:
var myWorkerFunction = function(input) {
var w = myFactory();
w.on('error', function() {
// How to tell caller of myWorkerFunction() I failed,
// and stop the rest of the myWorkerFunction function? (return false)
});
w.dothis();
w.dothat(input);
w.hokeypokey();
return w.finalize();
}
But how to trigger that "return" for myWorkerFunction inside that event listener function? I could have myWorkerFunction emit an "error" message too, but that just kicks the can to the next layer, and doesn't stop the execution of the worker script (i.e. if dothis() fails, don't keep going and call dothat(input)). Is there a programming pattern for situations like this?
EDIT: The one solution I could come up with is something like:
var myWorkerFunction = function(input) {
var w = myFactory();
var hasFailed = false;
w.on('error', function() {
hasFailed = true;
});
w.dothis();
if (hasFailed) return fa;se
w.dothat(input);
if (hasFailed) return false;
w.hokeypokey();
if (hasFailed) return false;
var out = w.finalize();
if (hasFailed) return false;
return out;
}
Which is not very elegant having to constantly check if we've failed or not before every line of code.
A couple thoughts on this. First you might want to take a look at Caolan McMahon's fine async nodejs library because it feels like you're reinventing flow control that would be handled quite well with 'async.waterfall'.
If you don't feel it's a good fit you - following the pattern you've adopted you could opt to post events on completion of each step (see the 'done' events in the sample below). This would allow you to listen for those events as indication that no error has occurred and that it makes sense to move onto the next step. Let 'finalize' take an optional error to allow your worker to differentiate normal vs abnormal completion. This is not tested but here's what something like that might look like:
var myWorkerFunction = function(input) {
var w = myFactory();
w.on('error', function(error) {
// Handle error, log whatever - and finalize with an error?
w.finalize(error);
});
w.on('doneWithThis', function() {
w.dothat(input);
});
w.on('doneWithThat', function() {
w.hokeypokey();
});
w.on('doneWithHokeypokey', function() {
w.finalize();
});
w.dothis(); //starts the ball rolling.
}
Rather than copy and pasting my code onto here, I have uploaded it to github. The RequireJS module does have a dependency on jquery.signalr and in tern has a dependency on jquery but also have a dependency on the javascript held in /signalr/hubs. There is a bit of config to do with Require.Config.
Basically what is happening is on the first time you load the page the connection is made to the hubs within signalr and the "server side" code is executed and does the desired thing. When you refresh the page it does not. All client side code is called, so for example:
var myViewModel = new MyViewMode();
myViewModel.init();
and within your init method you have
var connection = $.connection.myHub;
this.init = function() {
connection.server.myMethod();
}
this would then go off to
public MyHub : Hub
{
public void MyMethod()
{
Client.Request.populateSomeInformation() // I think it's request but I'm doing this from memory!
}
}
and then call
connection.client.populateSomeInformation = function () { .. )
but doesn't call this :(
It looks like a connection has been made (using the good old console.log() to see what it outputs) and indeed debugging the project it executes the code within the hub but there is no response made back to the javascript.
So wonderful people of the internet, where am I going wrong? Do I need to check the state of $.connection.hub.start(); before attempting to start it again?
Time for beer :)
I believe it should be
connection.client.populateSomeInformation = function () { .. )
(not connection.server)
http://www.asp.net/signalr/overview/hubs-api/hubs-api-guide-javascript-client#callclient
(observations on the code you have on github right now)
var isLoaded = false;
// ... some code that doesn't change isLoaded ...
if (isLoaded == false) {
scrollIntervalId = window.setInterval(function () {
signalRLoaded();
}, 30);
}
I think isLoaded will always be false at this point. Not sure what you intended this to accomplish.
var connection = $.connection.hub.start();
I don't think you're supposed to open the connection before defining any client functions. I don't see any client functions being defined here, so maybe you're doing that somewhere else? I don't know if it really matters other than if the server attempts to call a client function that hasn't yet been defined...
function SignalRReady(callback) {
if (isLoaded) {
callback(connection);
} else {
readyCalls = callback;
}
return SignalRReady;
}
SignalRReady.version = "1.0.0";
SignalRReady.load = function(name, request, onLoad, config) {
if (config.isBuild) {
onLoad();
} else {
SignalRReady(onLoad);
}
};
return SignalRReady;
I'm confused by this bit of code, probably because I don't see how it's being used. Is this an attempt at a kind of singleton? I see that SignalRReady is the "class" being returned for the module. You're not really returning an object, you're returning a constructor which implies that you're instantiating it in other places, something like
define(['SignalRReady'], function(sigR)
{
var srr = new sigR();
});
But then you have that load function defined that calls the constructor and makes this look all weird. How are you using this?
Anyways, I'm thinking you might be hitting some kind of race condition where the client function may not always be available at the time the server is trying to call it.
(additional comments/code 2013-09-06)
Your connection object is actually a jQuery promise ( http://api.jquery.com/category/deferred-object/ ).
If you're unfamiliar with promises, think of them generically as a queue of callbacks to be executed later. In this case, when connected, all the callbacks will be executed (in the order they were added). If a callback is added after being connected, it will get executed immediately. This is how your code is working now. You add the callback to the .done queue after the connection is made and is executed immediately.
If you insist on creating the connection object yourself, then you do not need to use the stateChanged event. You just add the callback to the .done queue:
define(function()
{
function signalRReady(callback)
{
if (window.connection == undefined) {
window.connection = $.connection.hub.start();
}
window.connection.done(callback);
}
signalRReady.version = "1.0.0";
return signalRReady;
});
However, I believe it's not a good idea to initiate the connection yourself. Because your module isn't a complete wrapper around SignalR such that people would only use your module to do SignalR stuff, you are not guaranteed (and cannot expect) other code will not initiate the connection. Especially if someone is adding your module to an existing codebase.
Your module is simply adding a new event, so keep it simple. Take the callback and execute it yourself when appropriate:
define(function()
{
function signalRReady(callback)
{
$.connection.hub.stateChanged(function (state)
{
if(state.newState === $.signalR.connectionState.connected)
{
callback();
}
});
}
signalRReady.version = "1.0.0";
return signalRReady;
});
Nowadays, promises are pretty popular. You might want to implement a promise-based module like:
define(function()
{
var deferred = $.Deferred();
$.connection.hub.stateChanged(function (state)
{
if(state.newState === $.signalR.connectionState.connected)
{
// executes all callbacks attached by the "ready" function below
deferred.resolve();
}
});
return {
ready: function(callback)
{
deferred.done(callback);
},
version: "1.0.0"
};
});
If callbacks are attached after the connection has been made, they are executed immediately.
Also, notice this example module's init function returns an object instead of a function. Since RequireJS will pass the same instance around to any module that requires it, state is maintained - we can use local variables instead of global.