Take this code for an example:
(() => {
const data = []
const ws = new WebSocket('ws:/localhost:5555');
ws.onmessage = (frame) => data.push(frame.data);
})();
Is it possible to look up the value of data without stopping the application, or breakpointing onmessage and waiting for it to occur? Is it possible to just look up the value of any variable that I know to be stored persistently somewhere?
Variables inside a function are private to within that function scope. Only code inside that function scope can examine them.
If you're in the debugger, you will need to be at a breakpoint inside that function scope in order to see that variable.
Sometimes it's appropriate to move the declaration of a variable to a higher scope so that after it is modified inside some local scope, it's value will persist and can be accessed from a higher scope. I don't know what real problem you're trying to solve here to know whether that makes sense for your situation or not.
More likely, since variables like your data variable get modified at some unknown time, the only way some outside code can know when to look at an updated value is by participating in some sort of event system or callback system that notifies outside that it now has a new value. In that case, it's common to just pass the new value to the callback or along with the event. Then the outside code gets the value that way, rather than having to declare it in some parent scope.
Related
As I understand, when using Svelte store with $ prefixed it's automatically subscribed to value changes.
Having the following code, whenever users.name store value is changed it should trigger one of the two statements.
<script>
if (!$userS.name) {
list = Promise.reject({message:'You are not allowed to view this section!'});
} else {
list = getList('api/carousel/' + escape(term));
}
</script>
But the only way the previous code is working is when the if statement it's prefixed by "$:".
$: if (!$userS.name) { ...
So why is need the extra reactive dollar sign if it's already subscribed to store value changes?
Your component init script, that is the code inside the<script> tag, is not reactive. It runs once when your component is created and that's all. Think class constructor.
Only the code in reactive blocks $: is kept in sync and reruns when (reactive) variables they contain change.
The $ prefix gives you the value inside the store. In your example, the user variable is the store itself. console.log it, you'll see it is an object with a subscribe method etc. The prefixed variable gives you the value inside the store. Behind the scene, Svelte makes a subscription to the store (i.e. calls its subscribe method) when your component is created, and unsubscribes when it is destroyed.
Meanwhile, if the value changes, the $ prefixed variable will be reactive. But it will only have an effect if it sits in a reactive context. That is, either a reactive expression/statement $:, or in the markup. This is true for any reactive source (props, top level variables...).
In node I see variables initialized global inside modules are getting mixed up [changes done by one request affects the other] across requests.
For Ex:
a.js
var a;
function printName(req, res) {
//get param `name` from url;
a = name;
res.end('Hi '+a);
}
module.exports.printName = printName;
index.js
//Assume all createServer stuffs are done and following function as a CB to createServer
function requestListener(req, res) {
var a = require('a');
a.printName(req, res);
}
As per my assumption, printName function exported from module 'a' is executed everytime a new request hits node and it will have different scope object everytime.
So, having something global inside a module wouldn't be affecting them across requests.
But I see that isn't the case. Can anyone explain how does node handle module exports of functions in specific [way it handles the scope of the cached module exports object] and how to overcome this shared global variables across requests within a module?
Edit [We do async task per request]:
With rapid requests in our live system. Which basically query redis and responds the request. We see wrong response mapped to wrong request (reply [stored in a global var in the module] of a redis look up wrongly mapped to diff req). And also we have some default values as global vars which can be overridden based on request params. Which also is getting screwed up
The first step to understanding what is happening is understanding what's happening behind the scenes. From a language standpoint, there's nothing special about node modules. The 'magic' comes from how node loads files from disk when you require.
When you call require, node either synchronously reads from disk or returns the module's cached exports object. When reading files, it follows a set of somewhat complex rules to determine exactly which file is read, but once it has a path:
Check if require.cache[moduleName] exists. If it does, return that and STOP.
code = fs.readFileSync(path).
Wrap (concatenate) code with the string (function (exports, require, module, __filename, __dirname) { ... });
eval your wrapped code and invoke the anonymous wrapper function.
var module = { exports: {} };
eval(code)(module.exports, require, module, path, pathMinusFilename);
Save module.exports as require.cache[moduleName].
The next time you require the same module, node simply returns the cached exports object. (This is a very good thing, because the initial loading process is slow and synchronous.)
So now you should be able to see:
Top-level code in a module is only executed once.
Since it is actually executed in an anonymous function:
'Global' variables aren't actually global (unless you explicitly assign to global or don't scope your variables with var)
This is how a module gets a local scope.
In your example, you require module a for each request, but you're actually sharing the same module scope across all requrests because of the module caching mechanism outlined above. Every call to printName shares the same a in its scope chain (even though printName itself gets a new scope on each invocation).
Now in the literal code you have in your question, this doesn't matter: you set a and then use it on the very next line. Control never leaves printName, so the fact that a is shared is irrelevant. My guess is your real code looks more like:
var a;
function printName(req, res) {
//get param `name` from url;
a = name;
getSomethingFromRedis(function(result) {
res.end('Hi '+a);
});
}
module.exports.printName = printName;
Here we have a problem because control does leave printName. The callback eventually fires, but another request changed a in the meantime.
You probably want something more like this:
a.js
module.exports = function A() {
var a;
function printName(req, res) {
//get param `name` from url;
a = name;
res.end('Hi '+a);
}
return {
printName: printName
};
}
index.js
var A = require('a');
function requestListener(req, res) {
var a = A();
a.printName(req, res);
}
This way, you get a fresh and independent scope inside of A for each request.
It really depends when in the process do you assign to name.
if between assigning the name to calling requestListener, there is an async method, then you we'll have "race conditions" (I.E. two threads changing the same object at the same time) even though node.js is single-threaded.
this is because node.js will start processing a new request while the async method is running in the background.
for example look at the following sequence:
request1 starts processing, sets name to 1
request1 calls an async function
node.js frees the process, and handles the next request in queue.
request2 starts processing, sets name to 2
request2 calls an async function
node.js frees the process, the async function for request 1 is done, so it calls the callback for this function.
request1 calls requestListener, however at this point name is already set to 2 and not 1.
dealing with Async function in Node.js is very similar to multi-threaded programming, you must take care to encapsulate your data. in general you should try to avoid using Global object, and if you do use them, they should be either: immutable or self-contained.
Global objects shouldn't be used to pass state between functions (which is what you are doing).
The solution to your problems should be to put the name global inside an object, the suggested places are inside the request object, which is passed to all most all functions in the request processing pipelie (this is what connect.js,express.js and all the middleware are doing), or within a session (see connect.js session middleware), which would allow you to persist data between different requests from the same user.
Modules were designed for run once and cache the module, that, combined with node's asynchronous nature means about 50% of the time res.end('Hi '+a) executes before a = name (because a is known).
Ultimately it boils down to one simple fact of JavaScript: global vars are evil. I would not use a global unless it never gets overridden by requests.
I had declared and used a global variable in ssjs library as below:
var backendDoc:NotesDocument = null;
function savedata () {
print (backendDoc.getItemValueString("fieldname")); // crash here
}
I assigned a document object to it in the Edit button just after changing docuemnt mode from read to edit:
backendDoc = document1.getDocument(); // get backend document from datasource called document1
The code in above function return error NotesDocument.getItemValueString("string")) null. Apparently, the backendDoc is null.
Any ideas how to assign value and use global variable in ssjs library? Thanks in advance
There are 2 problems with your code:
as Michael pointed out: you should use a scoped variable. Global variables in script libraries are actually application global (think applicationScope) and might be unloaded any time if memory gets tight (behavior of them depends on the XPages version)
You can't use NotesObjects here. Between the calls the C Object that backs the JS object is released and your object becomes invalid.
You can either store the NoteId in a scoped variable and retrieve the NotesDocument every time or actually use a JSON structure to keep the values you are interested in and only read/write when actually needed (load/save event). Hope this helps
I think you have to use a scoped variable in which you store the universalid of the document. This can then be used at any script to initialize the backend document.
From a ssjs you can set a scoped variable using the put method and the get method to read the variable. Example to set and read a scoped variable in session scope :
sessionScope.put(“myvar“,“myvalue“)
sessionScope.get(“myvar“)
To learn more about scoped variables watch this
http://notesin9.com/index.php/2009/11/07/episode-4-intro-to-scoped-variables/
I'm reading the cluster.js file of the cluster package and this part confuses me:
fs.readdirSync(__dirname + '/plugins').forEach(function(plugin){
plugin = plugin.replace('.js', '');
exports.__defineGetter__(plugin, function(){
return require('./plugins/' + plugin);
});
});
I know that you can bind objects or functions to the exports object to expose them to different files, but it seems that it is calling a function already bound to the object. However, I always thought you needed to require the file and access functions that way. What is going on here?
This is realization of lazy loading for plugins. Plugin will be loaded only after first access to module property with his name. __defineGetter__ is the 'syntax sugar' not presented in ECMAScript standard. It binds an object's property to a function to be called when that property is looked up.
If a module sets exports to a single function rather than an arbitrary object, then the result of require will be a function reference which can be called directly (note that a function is actually a type of object and as such can have properties, which can also be functions).
That's not what's going on here, though. At the time the code you've shown is executed, a function called __defineGetter__ has already been defined and attached to exports. Here it's simply being called as a method of exports (presumably because the author didn't feel the need to create a redundant local name for it).
i.e. somewhere along the line there's something like
exports.__defineGetter__ = function(propname, getter) {
...
}
Since it doesn't have a local name, the only way to call it is through exports.
Obviously the purpose of the code here is to allow you to call cluster.nameOfPlugin.method(...) without having to manually require each plugin, while not requiring all the possible plugins to be preloaded; instead only the ones you actually use get loaded.
I am making a simple debugger window in ActionScript for myself where I can add and remove variables I want to track. I was to be able to add variables to the list by just doing something like
DebuggerMonitor.trackVar(variable).
My question is, is there any way I can turn "variable" itself (the name, not the value) into a String to be added into a text field?
Depending on how "intelligent" your debugger should be, you could just pass the name along:
DebuggerMonitor.trackVar( variable, "variable" );
since obviously, when used in a context like this, the name should be known at the time you are writing the program.
You can also do some reflection magic to get instance variable names, but it won't work for temp variables (their names are dropped at compilation time):
public function getVariableName( instance:*, match:* ):String {
var typeDescription:XML = describeType( instance );
var variables:XMLList = typeDescription..variable;
var accessors:XMLList = typeDescription..accessor;
for each(var variable:XML in variables)
if(matchesXMLName( instance, variable, match ))
return variable.#name;
for each(var accessor:XML in accessors)
if(matchesXMLName( instance, accessor, match ))
return accessor.#name;
return "No name found.";
}
private function matchesXMLName( instance:*, xml:XML, match:* ):Boolean {
return match == instance[xml.#name.toString()];
}
var varName:String = getVariableName ( myObject, variable );
Using reflections like this will also be quite costly, if used often - you will have to think of a way to cache the type descriptions.
I recommend you check out the as3commons reflections package - there is a lot of useful functionality in there...
Short answer - No :(
You can access the type name but not individual instance names, as these are lost at run-time.
There is a confusion caused by the keyword 'var' because it is used to create several types of bindings.
Lexical bindings (the keyword 'var' was used inside a function).
Dynamic bindings (the keyword 'var' was used to declare a class' field).
Lexical bindings are interpreted by the compiler at compile time as addresses of the registers of the registers space occupied by the function. The names given to lexical bindings perish at this time and it is not possible to restore them at runtime - therefore you can't get the "name" of the variable.
Dynamic bindings are a kind of "public API" of the objects that declare them, they may be accessed from the code that was not compiled together with the code that created them, this is why, for the purpose of reflection the names of these bindings are stored in compiled code. However, ActionScript has no way of referencing LHS values, so you cannot, even if you know the name of the variable and the object declaring it, pass it to another function. But you can look it up in the debugger or by calling describeType on the object declaring the variable. Note that describeType will not show information on private variables even if you are calling it from the scope of the object in question.