Calling an exported function from within the same module - javascript

If you have a function like this in a module:
dbHandler.js
exports.connectSQL = function(sql, connStr, callback){
////store a connection to MS SQL Server-----------------------------------------------------------------------------------
sql.open(connStr, function(err, sqlconn){
if(err){
console.error("Could not connect to sql: ", err);
callback(false); //sendback connection failure
}
else{
callback(sqlconn); //sendback connection object
}
});
}
Can you call this from inside the same module it's being defined? I want to do something like this:
later on inside dbHandler.js
connectSQL(sql, connStr, callback){
//do stuff
});

Declare the function like a regular old function:
function connectSQL(sql, connStr, callback){
////store a connection to MS SQL Server------------------------------------
sql.open(connStr, function(err, sqlconn){
// ...
and then:
exports.connectSQL = connectSQL;
Then the function will be available by the name "connectSQL".

There are any number of ways to accomplish this, with Pointy's being my preferred method in most circumstances, but several others depending on the situation may be appropriate.
One thing you will see often is something like this:
var connectSQL = exports.connectSQL = function(sql, connStr, callback) { /*...*/ };
Technically, though I've never actually seen someone do this, you could use the exports object inside your module without issue:
// later on inside your module...
exports.connectSQL('sql', 'connStr', function() {});
Beyond that, it comes down to whether it matters whether you have a named function, like in Pointy's example, or if an anonymous function is ok or preferred.

Related

Uglify the global variable

I have an app in nodejs. In it, I define some global variables that are shared across multiple files. For example:
//common.js
async = requires("async");
isAuthenticated = function() {
//...
return false;
};
//run.js
require("common.js");
async.series([function () {
isAuthenicated();
}], function () {
console.log("done");
});
I want the async and isAuthenticated variables to be minified, but minified to the same thing in all files. It would look like the following:
//common.min.js
a = requires("async");
b = function() {
//...
return false;
};
//run.min.js
require("common.js");
a.series([function () {
b();
}], function () {
console.log("done");
});
How to do it in uglifyjs?
I'm currently looping through the files and using the command uglifyjs $file -m "sort,toplevel" -c > $file.min on each.
Don't use globals.
Use var async = reuqire('async') where needed.
Use module.exports in your specific modules you require.
Use something like browserify to generate a single js.
Uglify (or use a browserify transform named uglifyify)
For example, the simplest form (without using uglifyify)
$ browserify run.js | uglifyjs -c > run.min.js
Note that if you use your own code, like common.js, you should require it using a relative path, var common = require("./common").
I suggest you use the exports syntax:
// common.js code
exports.isAuthenticated = function() {
//...
return false;
};
And of course use it just as you would with async.js:
//run.js
var common = require("./common");
var async = require("async")
async.series([function () {
common.isAuthenicated();
}], function () {
console.log("done");
});
assuming both common.js & run.js reside in the same directory.
related question: How to get minified output with browserify?
A Side Note
The way you used async.series in your question has no real advantage. You could have just:
//run.js
var common = require("./common");
common.isAuthenicated();
console.log("done");
in Async series you usually call async functions:
async.series([
function(callback){
// do some stuff ...
callback(null, 'one');
},
function(callback){
// do some more stuff ...
callback(null, 'two');
}
],
// optional callback
function(err, results){
// results is now equal to ['one', 'two']
});
so, I would expect to see something like:
// common.js code
exports.isAuthenticated = function(callback) {
//...
callback(null, false);
};
and then
//run.js
var common = require("./common");
var async = require("async")
async.series([common.isAuthenicated], function (err, results) {
console.log("done with", results[0]);
});
I usually prefer a different "syntax"
// an example using an object instead of an array
async.series({
one: function(callback){
setTimeout(function(){
callback(null, 1);
}, 200);
},
two: function(callback){
setTimeout(function(){
callback(null, 2);
}, 100);
}
},
function(err, results) {
// results is now equal to: {one: 1, two: 2}
});
But it's your call.
The async examples were taken from https://github.com/caolan/async#seriestasks-callback
You would want to concat the files before you go ahead and uglify them. Concatenation is the process of combining multiple files of code into one monolithic creature that knows everything about all parts of your code. This is often done in conjunction with uglyfying for several reasons, mainly for performance benefits (your app runs a lot faster if you only send 1 file to the client).
That being said, this is typically a practice that is done when your serving code to a client, not necessarily for back-end / server-side logic. Ideally no one but you or people with access to whatever service you're using to deploy said server code should see that side of your code. If your main concern is to prevent reverse-engineering, or make your code unreadable, I suggest obfuscating your code.
"This is omega site. Best encrypted level he has. Looks like obfuscated code to conceal its true purpose. Security through obscurity." - Q Skyfall 2012
If your globals are confined to common.js, you may try
uglifyjs --define-from-module common.js $file...
and remove require()s.
In NodeJs there is the concept of defining global variables like posted in this thread:
global.myGlobalVar = "something visible to all modules";
I am too using uglify in my node apps, and it turned out that when using global.xyz, xyz does not get uglified.
disclaimer: I am totally aware that exposing global info is an anti pattern. But sometimes there is a good reason for it.
Hope that helps!

JavaScript and Cloud code function, share the same var

I use parse.comas backend service for my iOSapp. I was trying to do everything in objective-c since I don't have any experience with JavaScript, but turns out I will need to develop some Cloud Code Functions in JavaScript to complete my app.
A simple routine I'm trying to create:
User retrieves an object using a Cloud Function.
User saves another object in a different class.
An afterSavefunction runs in the cloud to update object first retrieved.
Now, here is my code:
var UserConfigOrientador = Parse.Object.extend("UserConfigOrientador");
var query = new Parse.Query(UserConfigOrientador);
Parse.Cloud.define('pegarOrientadorLivre', function(request, response) {
Parse.Cloud.useMasterKey();
query.greaterThan("entrevistasDisponibilidade", 0);
query.first({
success: function(results) {
response.success(results);
query = results;
},
error: function(error) {
response.error('Favor, checar rede e tentar novamente.');
}
});
});
// AfterSave
Parse.Cloud.afterSave("Agenda", function(request) {
Parse.Cloud.useMasterKey();
query.set("entrevistasDisponibilidade", 70);
query.save();
}
});
});
Now, the second function is not working, I'm getting the message that Object has no set method.
Basically, my questions are:
How can I share data between functions?
Should I keep everything in main.js or can I use another file?
I'm using webStorm for development. And the question about main.js is that after a while I will have a lot of functions and I am trying to figure out how to organize my code.
Your issue is one of scope, and poorly named variables that you're reusing for multiple purposes.
You define your query variable as a query, use it, but inside the success handler you set it to the result of the query (you now have a variable called query which is actually an instance of your UserConfigOrientador class).
When that Cloud Code finishes running, the result goes out of scope and is most likely set to undefined. You shouldn't be trying to share variables between multiple Cloud Code methods like that.
Is there something on the Agenda object that can let you know which UserConfigOrientador to update? Perhaps you could add a pointer property to the UserConfigOrientador? If you did, then you could use the following:
// AfterSave
Parse.Cloud.afterSave("Agenda", function(request) {
Parse.Cloud.useMasterKey();
var userConfigOrientadorQuery = new Parse.Query("UserConfigOrientador");
// read "userConfigOrientador" pointer property on "Agenda" object
var userConfigId = request.object.get("userConfigOrientador").id;
userConfigOrientadorQuery.get(userConfigId, {
success: function(userConfigOrientador) {
userConfigOrientador.set("entrevistasDisponibilidade", 70);
userConfigOrientador.save();
}
});
});
Mm.. I don't think it quite works the way you expect.
When your Cloud code runs, your initial var query declaration is indeed available within the scope of your cloud function and afterSave function. However, you're not passing it in correctly. As a matter of fact, I'm a little confused because your query seems to be requesting a UserConfigOrientador object while your afterSave is on an Agenda object.
So there are two different things going on here. Since you don't actually save an agenda object, I'm assuming that your response.success() returns a JSON of the UserConfigOrientador object back to client side at which point you do some manipulation then save the Agenda object based on that result.
At this point, when you save() the Agenda object now the afterSave() function will run but your query value will be the var query = new Parse.Query(UserConfigOrientador); which does not have a set method. This is why you get the error.
I'm not even sure your query = results; line will actually execute as you should be calling it at the END of your sub-routine and it signals to Parse that it is the end.
If you can tell me how you're saving the Agenda object I can probably complete the picture.
EDIT: --- abstracted but maybe this is the pattern you're looking for...
var ObjectA = Parse.Object.extend('ObjectA');
var queryObjectA = new Parse.Query('ObjectA');
Parse.Cloud.define('findObjectX', function(request, response) {
Parse.Cloud.useMasterKey();
// other query options here...
query.first({
// the first() function will return a Parse.Object
success: function(objectX) {
// Now you have objectX
// Now you want to save some other object
var otherObj = new ObjectA();
// Do things to otherObj
otherObj.save({
success: function(result) { // will be the saved otherObj
// Now you do stuff to your queried obj and save
objectX.set('something', result); // or whatever
// Note, it accomplishes what I think you want without afterSave()
}
}); // async... but we can just let this guy go
},
error: function(error) {
response.error('Favor, checar rede e tentar novamente.');
}
});
});

Efficiency with JavaScript Callbacks

I just wanted to confirm a suspicion of mine.
I stumbled across an article which recommended using Socket.io in the following fashion:
var app = require('express').createServer()
var io = require('socket.io').listen(app);
app.listen(8080);
// Some unrelated stuff
io.sockets.on('connection', function (socket) {
socket.on('action1', function (data) {
// logic for action1
});
socket.on('action2', function (data) {
// logic for action2
});
socket.on('disconnect', function(){
// logic for disconnect
});
});
I feel like the following would be a better use of resources:
var app = require('express').createServer()
var io = require('socket.io').listen(app);
app.listen(8080);
// Some unrelated stuff
io.sockets.on('connection', function (socket) {
socket.on('action1', action1);
socket.on('action2', action2);
socket.on('disconnect', disconnect);
});
function action1(data) {
// logic for action1
}
function action2(data) {
// logic for action2
}
function disconnect() {
// logic for disconnect
}
My feeling is that although the anonymous function that handles the connection event is only created in memory once, the anonymous functions that handle action1, action2, and disconnect are created in memory for every socket connection. The issue with the second approach is that socket is no longer in scope.
So firstly, is my suspicion about the creation of functions true? And secondly, if so is there a way to get socket in scope for the named functions?
Using a closure helps to keep the scope clean:
io.sockets.on('connection', function () {
function action1(data) {
// logic for action1
}
function action2(data) {
// logic for action2
}
function disconnect() {
// logic for disconnect
}
return function (socket) {
socket.on('action1', action1);
socket.on('action2', action2);
socket.on('disconnect', disconnect);
}
}()); // <- note the immediate function call
To your questions:
So firstly, is my suspicion about the creation of functions true?
Yes. The closure approach above prevents this, the callback functions are created only once. Plus: all see the correct parent scopes.
And secondly, if so is there a way to get socket in scope for the named functions?
The socket will be available as this in the callbacks.
You're correct, that the anonymous methods are created for each connection - and if you don't need scope, then the second method does avoid that. If you need the socket scope there's no real way to avoid it. If you want to keep the methods external (for some other reason) and still keep scope, you could always:
//...
socket.on('action1', function(){
action1.apply( socket, arguments );
} );
//... and so forth.
But that has you back to creating a method signature for each connection, so I'm not sure what you'd be gaining.

Catching module loading errors and processing them

I am trying to load some content using require.js. If the content doesn't exist I'd like to catch the error and notify the user.
In firebug I can see two errors:
"NetworkError: 404 Not Found
...and then a few seconds later:
var e = new Error(msg + '\nhttp://requirejs.org/docs/errors.html#
Load timeout for modules: modules/messages/messages
http://requirejs.org/docs/errors.html#timeout
My code resembles:
require([path], function(content){
//need to catch errors as this will not be called;
});
How would one bind to requirejs events? Any idea?
It is also possible to use errbacks to have customized error handling appropriate to the specific use of require. Errbacks are documented here http://requirejs.org/docs/api.html#errbacks. Basically, you can add to require a function to be called if the load fails. It comes right after the function to be called if the load is successful.
Chin's case could be handled as:
require([path], function(content){
//need to catch errors as this will not be called;
}, function (err) {
//display error to user
});
Here's an example that tries loading from multiple places:
require([mode_path], onload, function (err) {
if (mode_path.indexOf("/") !== -1)
// It is an actual path so don't try any further loading
throw new Error("can't load mode " + mode_path);
var path = "./modes/" + mode_path + "/" + mode_path;
require([path], onload,
function (err) {
require([path + "_mode"], onload);
});
});
In this example onload would be the function called once the required code loads, and mode_path is a string identifying the mode. What you see there is code attempting to load a mode module for an editor from 3 different locations. If mode_path is foo, it will try to load foo, then ./modes/foo/foo and then ./modes/foo/foo_mode.
The example at requirejs.org shows how one might handle a case where they want to try multiple locations for a resource they want to make available with a well-known identifier. Presumably the entire code-base in that example requires jQuery by requiring "jquery". Whatever location jQuery happens to be located at, it becomes available to the whole code-base as "jquery".
My example does not care about making the mode known to the entire code-base through a well-known identifier because in this specific case there's no good reason to do so. The onload function stores the module it gets into a variable and the rest of the code base gets it by calling a getMode() method.
set the requirejs onError function:
requirejs.onError = function (err) {
if (err.requireType === 'timeout') {
// tell user
alert("error: "+err);
} else {
throw err;
}
};
If you want to setup an event you could bind to and trigger a global object. Such as:
$("body").bind("moduleFail",function(){
alert("Handling Event")
});
requirejs.onError = function (err) {
if (err.requireType === 'timeout') {
$("body").trigger({type:"moduleFail",err:err})
} else {
throw err;
}
};
require(["foo"],function(foo){
alert("loaded foo" + foo)
})
Did you try to override the requirejs.onError like shown here?
It worked for me after setting catchError as true like this:
require.config({catchError:true});
before calling any define() or require() functions.
You can use the requirejs.onError function as :
requirejs.onError = function (err) {
if (err) {
//Reload
}
else {
throw err;
}
};
You can also use err.requireType to catch specific errors like timeouts

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