asynchronous JavaScript static function variable - javascript

I have a problem with a "static" function in javascrip (nodejs server).
User.create = function(data, _callback){
var node = db.createNode(data);
var _user = new User(node);
_user.save(function(err){
if(err) return callback(err, null);
_user.index(function(err){
if(err) return callback(err, null);
callback(null, _user);
})
})
};
If I call this function twice the _user variable in the internal callback function takes the new value, it seems it overrides the function var instead of allocate a new one.
I need calling this function to allocate a new variable, so it waits save and index functions to complete without changing _user variable.

JavaScript variables are indeed function scoped, so there wouldn't be any explanation for var _user not defining a new variable on subsequent runs.
Looking at the code, I would be more suspicious of what's happening in your User constructor - perhaps it contains some scoping or other logical issues resulting in identical users being created on subsequent calls. Similar "suspects" would be the data parameter getting passed in, as well as db.createNode(). Only suggesting these areas, because it's more likely that there's a programmatic issue at play, rather than JavaScript not following the rules :)
Also, I noticed that your User.create function accepts a parameter called _callback, but later on is invoking callback. I don't know if that's a typo in your example, or if you're accidentally invoking a callback from a higher scope not shown in the example, but that could produce weird behavior.

Related

Is it possible to get the local variable and parameter values with window.onerror

I have a simple javascript error logging mechanism in place and it looks somewhhat like this:
window.onerror = function (ErrorMsg, Url, LineNumber, Col, Error) {
// ajax these to the server, including Error.stack}
The problem is that I'd also like to get the value of the local variables and function parameters when the error occurred. Is this even possible?
I'm thinking about modifying the Function prototype so that each time a function runs, its arguments are stored in a global array of strings and then the error handler would just add this array to the ajax call. Can JavaScript do this?
#1 Can local scope be recovered in onerror() without black magic?
Without this being bound in the scope of window.onerror() or the surrounding variables being directly accessible, it's impossible to regain access to the variables you had set.
What you're mostly wanting access to is this.arguments or arguments or the equivalent, but that's destroyed. Any hope of obtaining a key-value associative array or hash-like object would involve meta-programming ( i.e. reading the function definition to obtain the variable names, and obtaining an exception report to attempt to salvage data ).
See this answer for more on something similar:
Getting All Variables In Scope
But this "lacking functionality" is a good thing:
If you could gain access to what you're asking for, that would likely be a fault in the Javascript engine. Why? Because the variable states and contents themselves are what caused the exception/error, assuming bad code wasn't the issue to begin with.
In other words, if you could get access to a faulty variable, that might be a door into an infinite loop:
Failure due to variable contents.
Error handler triggered.
Trace contents of variable.
Failure due to variable contents.
Error handler triggered.
Trace contents of variable.
Etc.
#2 Can Javascript store all arguments of every function call by voodoo?
Yes. It can. This is probably a really bad idea ( see #1 ) but it is possible. Here is a pointer on where to start:
Is there a way to wrap all JavaScript methods with a function?
From there, what you're wanting to do is push this.arguments or equivalent to a stack of function calls. But again, this is approaching insanity for many reasons. Not the least of which is the need to duplicate all the values, lest you reference mutated variables, or be unable to access the data at all... and like I said above, the problem of bad data in general. But still, it is possible.
Is this even possible?
No. A stack trace is proof that the stack has unwound, all stack frames and all the local variables they contained are gone. As for getting the name of a variable, that is not even possible at run time.
To start off i accept #Tomalak completely.
I was also put in your situation where i needed to debug a remote running app in case of crash.
As a work around I have forked my code for you in a fiddler. Please modify according to your need.
Caveat: You have to wrap the function body with try{..}catch(e){..} as illustrated in the fiddler code.
Please read the inline comments for understanding.
window.onerror = function (errorMsg, url, lineNumber, column, errorObj) {
console.log(errorObj);
}
window.addEventListener("reportOnError", function(e){
console.log(e.detail);
/*Send to the server or any listeners for analysis.*/
//Http.send(e.detail);
});
function ExceptionReport(ex, args, scope) {
var self = {};
self.message = ex.message;
self.stack = ex.stack;
self.name = ex.name;
self.whoCalled = args.callee.caller.name == "" ? "Window": args.callee.caller.name;
self.errorInFunction = args.callee.name;
self.instanceOf = scope.constructor;
self.KeyPairValues = getParamNames(arguments.callee.caller.toString(), Array.prototype.slice.call(args)); //Contains the parameters value set during runtime
window.dispatchEvent(new CustomEvent('reportOnError', {'detail':self}));
}
//Utilties
function getParamNames(fnBody, values) {
var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg,
ARGUMENT_NAMES = /([^\s,]+)/g,
result = fnBody.slice(fnBody.indexOf('(')+1, fnBody.indexOf(')')).match(ARGUMENT_NAMES),
obj={};
fnBody.replace(STRIP_COMMENTS, '');
if(result !== null){
for(var i=0; i < result.length; i++){
obj[result[i]] = values.length !==0 ? values[i] : null;
}
}else{
obj = null;
}
return obj;
}
/*
This is a testing/sample function that throws the error
*/
function testing(a,b,c){
try{
dummy(1,2) ; //This line throws the error as reference error.
}catch(e){
ExceptionReport(e, arguments, this);
}
}
//Class Emulation: For instanceof illustration.
function testingClass(){
this.testing = testing;
}
//Named self executing function: This calls the function
var myvar = (function myvar(){
testing(1,2,3);
})();
//Illustrating instanceof in exception
var myVar2 = new testingClass();
myVar2.testing(1,2,3);
//Calling from global scope this is Window
testing(1,2,3);
//Without variables
testing();
I have used examples to illustrate the behavior of functions called in different circumstances.
Below signifies the varialble used for
self.KeyPairValues : Used to store the function parameter set/passed during runtime
self.errorInFunction : This stores the name of the function error was caused in.
self.whoCalled : This stores the function name that invoked the defective function
self.instanceOf : This stores the name of the instance is called creating a new instance.
Other variables are same as in Error object
The others answers here are spot on, but I might be able to offer a suggestion for a slightly different way to accomplish this. Instead of trying to track all scope in your program, why not add a tagging function that tracks the scope of one function's parameters without affecting the runtime of the function. For for example:
var globalRecord = {};
function record(name, fn) {
return function () {
var args = [].slice.call(arguments);
var record = globalRecord[name] = {
args: args,
arg: {}
};
args.unshift(function (name, value) {
return record[name] = value;
});
fn.apply(args, arguments);
}
}
// Then, you track variables like this
var func = record("func", function (record, a, b, c) {
record("a", a); // named parameters are accessible now
record("b", b); // if some error occurs in the function body
return a + b + c;
});
// Calling func still behaves as before.
func(1, 2, 3);
// Errors handled like this:
window.onerror = function () {
globalRecord.func.args; // ==> last set of arguments past to function
globalRecord.func.arg.a; // specific arguments recorded with names
};
You could even use this method to track scope without using a function by anonymously calling the recorded function.
record("test", function (record) {
var a = record("a", /* whatever */);
var b = record("b", /* ... */ );
// do scope specific stuff that might fail
})();
Of course, this isn't a polished implementation by any stretch, but with a little work, I think you might be able to get the behavior you're looking for without any seriously black magic. By selectively adding and removing record calls as the need presents itself, you can have precise control over what is logged without any intrusive hacks.
You can find your answer in this link.
Before taking bundles from the server, you must modify them. For example, to solve your problem, you can do changes in the mentioned link as follows. In the BuildBundleContent Class make this change:
contents.Insert(blockContentIndex,
string.Format("if(customErrorLogging)customErrorLogging({0}, this){1}",
errVariable, hasContent ? ";" : ""));
If in the modules you have to use something like:
var self = this;
You can use:
contents.Insert(blockContentIndex,
string.Format("if(customErrorLogging)customErrorLogging({0}, self ? self : this){1}",
errVariable, hasContent ? ";" : ""));
And in added js file:
"use strict";
var customErrorLogging = function (ex, module) {
console.log(module);
//do something...
};
I hope help you.

Updating parameters to JavaScript callback before it returns, without using globals

I'm working on making a modification to a node.js module to improve error handling for one of my uses cases. The specifics of the module aren't really relevant, but one of the things I want to do is trigger a delayed retry when receiving a certain status code from the response to an API request. To do this I'm using the timeOut function to trigger a new call to the function after a period of time.
The structure of the code looks like this:
Outer function (parameters specified by client application)
——API request (using parameters)
——Callback from API request (response with status code)
——If error, set timeout to call outer function after delay
However, I also want to handle the case that the outer function is called again while waiting for the timeout. I don't want any calls to trigger a new API request while a timeout is pending, but I do want the parameters from the most recent call to be used when the timeout finishes.
I've been able to get this working using variables that are global to the module. Each time a new call comes in to the outer function it updates a global object with the new parameters then, if a timeout is pending, returns without calling the API request. The timeout function uses the parameters from the global object to call the outer function, rather than the parameters from when it was set. This way it always uses the most recent values that were passed into the outer function, but doesn't make duplicate API calls.
Here's a simplified example of how I've achieved this behavior with global variables: JSFiddle. Hit run a few times until you get a "failure response" which then triggers the timeout.
This works, but I would prefer not add these global variables into the module if there's a better way.
Is there any way to get this same behavior but have all of the state encapsulated in the outer function without using globals? I'm also open to completely rethinking the way I'm handling this if anyone has ideas.
You're not going to be able to do this without creating variables outside of your outer function, however it's still possible to create those variables without polluting your global scope.
To do so, wrap your outer function in another function that gets executed immediately, sometimes known as an IIFE:
mainFunction: (function() {
var savedParam1;
var savedParam2;
var savedParam3;
var pendingTimeout = false;
return function(param1, param2, param3) {
savedParam1 = param1;
savedParam2 = param2;
savedParam3 = param3;
if (pendingTimeout) {
log('pending timeout -- ignoring new call');
return;
}
/* and so on */
}
})(); // the () causes the outer function to run immediately,
// which creates a scope for the savedParam / pendingTimeout variables,
// and then returns the inner function (your old outer function)
// to be used for mainFunction

Variable in parent scope not getting altered in anonymous function [duplicate]

This question already has answers here:
Why is my variable unaltered after I modify it inside of a function? - Asynchronous code reference
(7 answers)
Closed 8 years ago.
I'm using the opentok SDK for video chatting, and I need to create sessions. It's pretty straightforward, and that part's working fine. This is all being done in node.js, server side.
The issues is - and it's mostly cause I still don't quite get var scopes (especially with anonymous functions and closures) - I have a value inside of my anonymous function that I want to access (preferably by assigning it to another var, one that's in its parent scope), but can't!
Something like this:
function generateSession(session){
var session='';
opentok.createSession(function(error, sessionId){
if (error) {
throw new Error("Session creation failed.");
}
session = sessionId;
});
return session;
}
session retains it's initial value of '' (empty string), not the sessionId it was assigned to. Help?
This isn't a question about scope. It's about asynchronicity. Your anonymous function will update the session variable in the parent function; but because your anonymous function is asynchronous, it'll happen after generateSession has returned.
Instead, you'll need to modify generateSession to accept a callback, and execute the callback (passing the generated session), once it's completed;
function generateSession(session, cb){
opentok.createSession(function(error, sessionId){
if (error) {
throw new Error("Session creation failed.");
}
cb(sessionId);
});
}
generateSession(blahblahblah, function (session) {
// Access session here.
});
This is the exact same problem as for How do I return the response from an asynchronous call? (in that situation, it's the "success" callback that is asynchronous); there might be a more suitable duplicate, but I can't find one :(. It'll still be beneficial to read through it though.
createSession is an asynchronous function. Its callback is not executed until some time after generateSession has finished. You need to pass in a callback instead:
function generateSession(cb){
opentok.createSession(cb);
}
generateSession(function(err, sessionId) {
if (err) throw err;
// use sessionId
});

Return 'undefined' variable from a function

I am new to javascript, and can't find the solution to this.
I have read some of the similar questions, but did not look like the problem was the same as mine.
I call a method from script1 with this code:
function turnPage(){
var current = window.now;
var nextpage = getNextPage(current);
alert(nextpage);
}
In script2 there is a SQLite etc:
function getNextPage(Pid) {
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM Page WHERE Pid=' + Pid, [],
function(tx, results) {
nextp = parseInt(results.rows.item(0).NextPage);
//alert(nextp);
return nextp;
}, errorCB);
}, errorCBQuery);
}
if I use the alert-dialog in the called function, the variable nextp is 2.
BUT if I return the variable, it will alert as 'undefined'.
Also, if I etc make the variable var nextp = 11; over "db.transaction..." and the return-statement at the end of the function, it will return 11 instead of 2.
Is it because the variable is not sent to the inner function in my inception of functions? :)
Any ideas of what to do? thanks!
I don't know how SQLite in javascript works, but I suspect it works asynchronously, so you're calling alert in turnPage but the transaction is running async and the return value is in another scope anyway. You can try passing a callback function to getNextPage and then instead of returning nextp call the callback with nextp as argument:
function turnPage(){
var current = window.now;
getNextPage(current, function (nextp) { alert(nextp); /* do whatever else you need to do */ });
}
function getNextPage(Pid, cb) {
db.transaction(function(tx) {
tx.executeSql('SELECT * FROM Page WHERE Pid=' + Pid, [],
function(tx, results) {
nextp = parseInt(results.rows.item(0).NextPage);
cb(nextp);
}, errorCB);
}, errorCBQuery);
}
Your outer function never actuallay returns nextp at any time.
There are two solutions to what (I think) you are going to do
Create a global variable and store the value of nextp there.
Introduce another callback to use the value of nextp, e.g., create a new link or whatever. If you want, you can put the code either in another function and pass it as a parameter to getNextPage() or put the code directly into the most inner function (at the position of your alertcall).
Note that callbacks are used to handle the asynchronous nature of many JavaScript APIs. So even your getNextPage() can't return the value of the inner query as that value is not present, when getNextPage() is finished.
Anyway the return statement in the most inner function can be dropped as there is no function to actually receive that value.
As it is now, there are several problems with your code.
As JavaScript mostly is asynchronus, your code:
nextpage = getNextPage(current);
alert(nextpage);
Will call getNextPage() but it will not wait for the response before moving on, so the alert will be fired right away, and at that point, if the response hasn't been returned and assigned (which is likely to be the case), then nextpage will be undefined.
Your second problem is that your outer function does not return anything. You return the value from your inner function, but then "it get stuck" in your outer function. One solution would be to assign the value to a global variable, instead of returning it from the function. You would still have to look out for the "asynchronous-problem", so that you don't read the global variable until it has been assigned.

Using factory methods as alternative to passing anonymous functions

I was watching a video on node.js and I saw the speaker say, he prefers to do this instead of using anonymous call backs:
var server = Server.createServer(server.createReq(req,res));
I think its nice too that a named function with parameters can be passed instead of an anonymous function with closure.
Question 1: However the implementation of the createReq probably returns an anonymous function, wouldn't it?
How is this better? I can see it being better because unlike the closure at the createServer level, a closure at the createReq level is more contained - it would not store reference to other unnecessary variables (non req,res).
And as the speaker said, I guess this would help visualize realtionships better between the different parts of the code.
Question 2: Are there any other benefits?
A reason why you might want to call a function that returns a function may be that you are starting multiple servers within the same process, and you want them to share the same request handler.
Another thing to keep in mind is that each anonymous function must be allocated on the heap, and thus incurs some garbage collection overhead. By using a named function instead of an anonymous function, you can sometimes reduce this cost.
For example, maybe something like this untested and incomplete example:
var server = Server.createServer(handleRequest);
function handleRequest(req, res) {
new Client(req, res);
}
function Client(req, res) {
this.req = req;
this.res = res;
this.body = "";
req.on("data", function (chunk) {
self.onData(chunk);
});
}
Client.prototype.onData = function (chunk) {
this.body += chunk.toString();
};
This example uses a small anonymous function to bind the data event callbacks back to the specific instance of Client, but all other functions are named.

Categories