LostInTheTrees
LostInTheTrees

Reputation: 1145

How do I modularize my code in JavaScript?

I am using Parse.com javascript for CloudCode. I have little interest in becoming an expert in javascript, but I need to do some. I have worked out a scheme for modularizing (dividing into separate files) but it seems like there must be a better way. In my main.js, I have code like this. The only function of main.js is to call and link the various modules together.

var mods = {};

mods.functions = require('cloud/functions.js');
mods.user = require('cloud/user.js');

mods.functions.setMods(mods);

The mods variable collects references to each module. Then for each module that needs to call other modules, I call "setMods" in that module and pass mods to it. In setMods the module gets references to any other module it wants to access.

Each module then has code like this.

exports.setMods = function (mods) {
    userMod =     mods.user;    
    constants =   mods.constants;    
};

Parse.Cloud.define("getRecoveryQuestion", function(request, response) 
{
    var p0 = userMod.lookupUserByEmail(request.params.email);
    var p1 = p0.then(function(user) {
            // result is a User
            // Now look for the password recovery question
            if (user) {
                // Found it
                var question = user.get("pwdRecoveryQuestion");
                response.success(question);
            } else {
                response.success(null);
            }
            return null;
        });
});

In the User module, the exported function would look this way.

exports.lookupUserByEmail = function (email)
// returns null when not found
{ 
    var User = Parse.Object.extend("User");
    var query = new Parse.Query(User);

    query.equalTo("email", email);
    var p0 = query.first();
    var p1 = p0.then(
        function(result) {
            return result;
        }
    );
    return p1;
};

So, is there a better solution to this problem?

Upvotes: 2

Views: 4021

Answers (1)

Esteban
Esteban

Reputation: 2579

There's no need to centralize module import in main.js. Every file in node.js is a module that will most likely have private code and export an interface. And it can import as many modules as it needs. This is the simpler way of importing your modules' dependencies:

getRecoveryQuestion definition

var userMod = require('cloud/user.js'),
    constants = require('cloud/constants.js);

Parse.Cloud.define("getRecoveryQuestion", function(request, response) 
{
    var p0 = userMod.lookupUserByEmail(request.params.email);
    var p1 = p0.then(function(user) {
            // result is a User
            // Now look for the password recovery question
            if (user) {
                // Found it
                var question = user.get("pwdRecoveryQuestion");
                response.success(question);
            } else {
                response.success(null);
            }
            return null;
        });
});

The User module would look like this.

cloud/user.js

exports.lookupUserByEmail = function (email)
// returns null when not found
{ 
    var User = Parse.Object.extend("User");
    var query = new Parse.Query(User);

    query.equalTo("email", email);
    var p0 = query.first();
    var p1 = p0.then(
        function(result) {
            return result;
        }
    );
    return p1;
};

Please keep in mind that what you pass to require is a module id. It can be a path (like in the case above) or a module name that will be looked for in a node_modules folder under the root of the project. Several Parse-provided modules will be there for you in their platform. In the previous example, I assumed both constants.js and user.js were in the cloud directory.

However, what you do in your code looks more like dependency injection. There are several reasons you might want to do dependency injection when coding (however, confirm that you do before adding one more layer of complexity to your codebase). Node's module.require implements the module pattern, which makes DI obsolete.

One of the main reasons for dependency injection is testing. You can change what require returns by using a handy library called proxyquire, avoiding the usage of a dependency injection library/framework.

If you have other reasons to do DI (for instance if you still feel uncomfortable about your code's coupling, or whatever), some people have written libraries for it. Check this SO question.

Upvotes: 1

Related Questions