In my main.js, I am reading a file asynchronously. Once my file is loaded, I set some objects in GLOBAL namespace and use them in my required modules (using GLOBAL namespace or not is a different story, I am using it anyway).
My required module immediately expects that variable to exist at the time of loading. So how do I make it wait till my file reading is complete in the main.js? Do I simply require module in the callback of readFile? Or there's a better way to do it?
example:
fs.readFile('./file', function (data) {
// do something
GLOBAL.obj = data;
});
require('./module.js');
module.js
obj.someFunction();
Your gut feeling of disliking that solution is understandable. (Your stomach is right). The proper way of cleaning this up (and you should take the time – future-you will thank you for it):
go through every one of your ten modules
for each one go through all the functions it exports
for each function figure out, what globals they actually depend on.
add those as arguments to the function.
if they take a lot of arguments now, consider grouping them into objects, creating useful models.
if a bunch of functions all depend on the same set of variables, you can also consider creating a factory function
create a function that takes the formerly global variables as arguments and wrap all of the module's code into that function.
make that function the single export of your module. It serves as a factory function and creates the context for all the other functions in that module. It should return whatever the module exported before.
Example
// DB used to be a global
module.exports = function(DB) {
function getUser(user, cb) {
DB.get('user', db);
}
return {getUser: getUser};
};
You can then use it like this:
var module = require('module')(DB);
module.getUser(myUser, function(){}};
Yes, just follow the rule #1 of async programming. Stuff that depends on callback happening must be executed in that callback. Since your require depends on the variable set in async, you can only use your require inside it:
fs.readFile('./file', function (data) {
// do something
GLOBAL.obj = data;
require('./module.js');
});
Related
I have the js modules defined below (example). This code was working in a standalone test webpage but after I migrated to an MVC app the vars/aliases defined towards the top of the module are resolving as "undefined" when referenced in the module function. However, if I change the reference in the function to the fully qualified object reference then the reference resolves without issue. Any idea what the issue might be or what is needed for the aliases to resolve successfully?
var ns = Acme.Utility.NamespaceManager.CreateNS("Acme.ReportApp");
ns.DailyReport = (function (){
var globals = Acme.ReportApp.Globals;
var getDailyReport = function() {
return{
AppName1:globals.AppName, //this fails
AppName2:Acme.ReportApp.Globals.AppName, //this succeeds
ReportName:'Daily Report'
};
}
return{
GetDailyReport : getDailyReport
};
})();
var ns = Acme.Utility.NamespaceManager.CreateNS("Acme.ReportApp");
ns.Globals = (function (){
var appName = 'Reporting Application';
return{
AppName : appName
};
})();
I'm using SystemJS to load the modules like this:
SystemJS.import('Globals.js')
.then(function(){SystemJS.import('DailyReport.js');})
.then(function(){Acme.ReportApp.DailyReport.GetDailyReport();})
When the then() function gets hit:
Acme.Report.App.Globals can be accessed in the final then but Acme.Report.App.DailyReport is undefined. Why would the final then() function have access to Globals but not DailyReport? Shouldn't the code above load the modules in sequence so by the time the final then() function gets called all modules should be loaded and available?
One interesting note is that the first import can be accessed as expected in the final then() function above. So if I imported DailyReport first then I'd be able to access DailyReport in the final then() function but not Globals. So it appears that maybe I'm doing something incorrectly in the import chain?
You are immediately executing that first function, which accesses Acme.ReportApp.Globals;. If that second function hadn't run yet, that won't be defined. Your code is execution order dependent:
var globals = Acme.ReportApp.Globals; // <- nothing has defined this
Even if Acme.ReportApp.Globals is set later on, your globals reference will continue to be undefined.
I'd recommend you either:
Make sure your modules are defined in the right order.
Don't dereference a "module" in your module constructors, only in their methods.
Use a real module system (CommonJS, AMD, etc).
Update:
Thanks for posting your import code as well. That makes things a lot clearer. There is a subtle bug in this code:
SystemJS.import('Globals.js')
.then(function(){SystemJS.import('DailyReport.js');})
.then(function(){Acme.ReportApp.DailyReport.GetDailyReport();})
The second line should have this instead:
.then(function() { return SystemJS.import('DailyReport.js'); })
...otherwise the Promise chain won't wait for that second import Promise to complete before running Acme.ReportApp.DailyReport.GetDailyReport();.
Reworded:
A common pattern is to pass callback functions, such as with Mongoose's save (just for example and simplified - no error handling):
someMethod(req:Request, res:Response){
document.save( function(err){ res.status(200).send({message: 'all good'})});
}
I'd like to externalize the callback. You can do this this way:
var respond = function(err:any, res:Response){
res.status(200).send({message: 'all good'});
}
someMethod(req:Request, res:Response){
document.save( function(err){ respond(err, res)});
}
...but ideally I'd like to do this by just passing a function like respond without having to create a call back function to enclose respond. I wanted to know if this is possible. Since the anonymous function has access to res, I thought there might be some way to gain access to res in a function defined externally. It appears there is not a way to do this so I'll live with wrapping it.
My original question was trying to isolate the specific issue I was interested in - which is to gain access to the caller's variables implicitly. Doesn't seem like that is possible. Fair enough.
Original Question:
I'd like to externalize a bit of code I use frequently and I'm having trouble understanding closure in the context of a Typescript method. Take a look:
var test = function(){
console.log("Testing external: "+JSON.stringify(this.req.body));
}
class Handler {
static post(req: Request, res: Response){
(function(){
console.log("TESTING anon: "+JSON.stringify(req.body));
}) ();
test();
}
}
Besides the fact that this does nothing useful, in this bit of code, the inline anonymous function has access to the req object, but the test() function does not. this in test is undefined. Removing this to match the inline function doesn't help.
I believe if I were to bind on this for the call I'd just end up with a reference to the Handler class when I really want to bind on the post method.
My motivation for doing this is that I want to make a function that can be passed as a callback to a bunch of different request handlers. When I write the functions inline it all works, but when I externalize it I can't get a closure over the variables in the enclosing method. I've read "You Don't Know JS: this & Object Prototypes", and in pure Javascript I can manage to make these sorts of things work but I'm obviously doing something wrong here (it may not be Typescript related, maybe I'm just messing it up).
So bottomline - is there a way I can externalize the handler and get access to the method variables as if I were writing it inline? I could just create an inline anonymous function as the callback that calls the external function with all the variables I need, but I want to really understand what is happening here.
This is not an answer, but will hopefully give me enough feedback to give you one because its not at all clear what you're actually trying to accomplish here and whether or not you actually understand what the terms mean is an open question since you use them correctly one minute and sketchily the next.
var test = function(){
console.log("Testing external: " + JSON.stringify(this.req.body));
}
In strict mode this will throw an error, in sloppy it will try to access the req property of the global object which is not likely what you want.
(function(){
console.log("TESTING anon: "+JSON.stringify(req.body));
}) ();
The IFFE wrapper is completely unnecessary, it literally adds nothing to the party. So why include it?
static post(req: Request, res: Response){
console.log("TESTING anon: "+JSON.stringify(req.body));
test(); // is this the spot where you are 'in-lining?'
}
What I think you want is this:
var test = function(reqBody) {
console.log("Testing external: " + JSON.stringify(reqBody));
};
class Handler {
static post(req: Request, res: Response) {
test(req.body);
}
}
I read some JS module design patterns recently. I came across this small code snippet as below.
(function(window) {
var Module = {
data: "I'm happy now!"
};
window.Module = Module;
})(window);
Still not quite understand this code well, my questions are:
How to use/call this module outside this particluar JS file? Need I
assign a variable to this module? e.g. var module1 = (...)(...);
Could anyone explain what the window parameter here stands for?
Is it a good practice to have two/three such kind of modules in the
same file?
The main reason to create an anonymous function in this case is to prevent global object pollution. It's not really a module pattern.
The problem arise when you declare a variable. Without the function scope, the variable will be added to the global object (window). If you were to declare the variables within a function. It would add the variable to the function scope without polluting the global object window.
What happen is that a javascript file could add a variable named foo and on a different file use that variable named foo too. Unless you really want to have a variable shared by two javascript files, it would probably create conflicts and bug that are difficult to fix.
For example: a.js
var foo = "one"
b.js
var foo = "two"
c.js
alert(foo)
In this case, the alert box might show either "one" or "two", depending of the order in the javascript files are included.
But having this a.js:
(function () {
var foo = "one"
})()
b.js
(function () {
var foo = "two"
})()
c.js
(function () {
alert(foo)
})()
This would create an error as you cannot alert a non declared variable.
One way to detect undefined variables, is to make sure to execute the javascript code in strict mode.
To do that, add the string "use strict" at the top of the file or function.
function () {
"use strict"
...
}
Undeclared variable will raise errors and it should be possible to fix the code that way.
Also, if you forget to declare a variable with the var keyword, it might end up adding the variable to the global scope even if the code is scoped into a function. The only way to prevent global scope pollution is to run the code in strict mode.
In the code snippet that you provided, the module with name Module is explicitly added to the window object. You can access the window object from any place in javascript unless the window name is ghosted by an other variable.
Now, back to the modules. If you want to define modules, it can be done in many ways. As an exemple, you could create an object on the window object called modules. In this object, you'll insert your modules.
module.js
window.modules = {}
foo.js
(function (window) {
var module = {}
...
window.modules.foo = module
})(window)
This variant isn't super good as you have to manually add the module to the modules object. You have to manually modify the window object, and that can be subject to errors.
modules.js
window.modules = {}
function define(name, constructor) {
var module = {exports: {}}
constructor(module)
window.modules[name] = module.exports
}
function require(name) {
return window.modules[name]
}
foo.js
define("foo", function (module) {
module.exports.one = function () {
return 1
}
module.exports.plus = function (a, b) {
return a + b
}
})
bar.js
define("bar", function (module) {
module.exports = function () {
var foo = require("foo")
return foo.plus(foo.one(), foo.one())
}
})
This is a module definition that looks a bit like module defined with http://requirejs.org/. It is quite basic as it doesn't take into account module dependencies so if bar is loaded and used before foo. Then the require method won't be able to return the module.
Also, if you want to store modules without having them visible into the global scope, you can only define the require and define method on the window object and hide modules into an anonymous scope like this:
(function (window) {
var modules = {}
function define(name, constructor) {
var module = {exports: {}}
constructor(module)
modules[name] = module.exports
}
function require(name) {
return modules[name]
}
window.define = define
window.require = require
})(window)
This way, define and require are the only function that can give you access to modules. Other modules won't be able to modify other modules without requiring them first. This can be useful when using third parties script that could conflict with your module system.
In fact this is not a module, but a Self-Invoking Ananymous function or an Immediate function which gets an object in parameter and assign a Module property to it:
The page window is a parameter passed to this function.
So an object named Module containing a data property is assigned to window.
JavaScript Self-Invoking Functions:
A self-invoking expression is invoked (started) automatically, without being called.
Function expressions will execute automatically if the expression is
followed by ().
You cannot self-invoke a function declaration.
You have to add parentheses around the function to indicate that it is
a function expression
So As you can see Immediate Functions can't be called as its name states it will be immediately executed and by its self, no other function or scope can execute it.
For better reference take a look at :
Javascript Self Invoking Functions.
Self-Invoking Functions section in JavaScript Function Definitions.
And concerning your last question about its benefits and good practices as shown on the given Article reference:
Where to use self-executing functions?
One obvious situation is when you want to auto-run a function like I
showed in above example but that is trivial. If you are in a situation
where you want to run a piece of code repeatedly like updating
something in the database based on user interaction or fetching
records from database every 10 seconds or you want to load new stories
via ajax similar to how facebook does on its homepage or some other
similar situation, one would normally go for setInterval function
something like this:
setInterval(doStuff, 10000);
Above, doStuff function will get called every 10 seconds. That is the
normal approach most developers seem to go with. However, there is a
huge problem with that.
The setInterval will call doStuff function exactly at specified time of 10 seconds again and again irrespective
of whether doStuff function actually finished doing what it is
supposed to do. That is bad and will certainly get you into unexpected
results.
That is one example of where setInterval is "bad" and should be
avoided.
This is exactly where self-executing functions come in handy. We can
do the same task with the help of self-executing function along with
setTimeout like this:
function foo(){
// your other code here
setTimeout(foo, 10000);
}();
This code will also repeat itself again and again with one difference.
setTimeout will never get triggered unless doStuff is finished. A much
better approach than using setInterval in this situation.
Calling it from another file:
And if this function is on another file it will be called automatically if this file is included.
Why do we use Self-Invoking Functions in JavaScript?
And if you ask yourself why do we use these functions, self-invoked function are used to manage Variable Scope.
Take a look at the answer here for further information.
I have a NodeJS application and I want to execute some method for file validations but just one time (this method will validate some files under the node application).
Is there an elegant way to do this? Events?
The NodeJS documentation on modules states that:
Modules are cached after the first time they are loaded.
which you can take advantage of by adding static code to the module. Regardless of how many times the module is loaded, the static code will retain its state(/value).
You can use that state from a method to implement a method that can be called whenever you like -- at the best time during initialization -- but only ever be called once. This is pretty simple:
var called = false;
function checkFiles() {
if (called) return;
// Perform your validation
called = true;
}
module.exports = {
checkFiles: checkFiles
};
Because of the module caching, you can require this file in as many places as you need and it will still only execute once.
To invoke this function, you have a few options:
For a simple application, you can call the function from your main module (or function) and it will be invoked at that time. If the validation should be asynchronous, you can wrap your main method in a function and pass that to the validator as a callback.
//#! /bin/env node
var express = require('express');
var validator = require('./validator');
validator.checkFiles();
var app = express();
var server = app.listen(3000, function () {
...
});
For a more complicated application, you should call this function during your existing initialization routine (again, using callbacks as necessary).
If you have a nice modern promise-based initializer, you could simply add the validator as the first step of the chain.
I am learning node.js and JavaScript. Following is the code. I found the var http is outside the function start2. I am wondering why it works? Since we only exports function start2, right?
Is this some concept about closure? (I've tried put the var http inside the start2. It works for sure.)
var http = require('http');
function start2(){
function onRequest(request,response){
console.log("Request recieved");
response.writeHead(200,{"Content-Type":"text/html"});
response.write("<h1>Hello world</h1>");
response.end();
}
http.createServer(onRequest).listen(8888);
console.log("Server has started.");
}
exports.start=start2;
You could put var http = require('http'); inside your function but most often that's not how people code it. People place it at the top like you have it. Why? This is a call to the module system to load module http. Most often, you want to do this once and make it available for your entire file. If you are doing to use this module multiple times in your file you don't want to call require again and again.
If a module it is rarely used and perhaps expensive to load, then it may make sense to have the require call inside a function, instead of paying the cost of loading it each and every time:
function calledUnderExceptionalCircumstances() {
var expensive = require('expensive');
expensive.foo();
}
In the code that you have attached, require loads a module into the global scope. Since you have defined function start2 in the same scope, due to closure, var http is available inside function start2.
In the second code snippet you have provided, due to closure, the reference to the variable env_var1 is made available inside f1, which is getting re - assigned.
If at all, instead of directly re - assigning env_var1 if you are redefining env_var1 as var env_var1, var env_var1 becomes a local variable and it's scope is confined within f1 and inside f2, it would print "aaa" instead of "bbb" as you would have expected.
Hope this helps.