0

Using requires, I’ve split larger class structures down into modules that use other modules within directory. There’s a main file that instantiates the other sub modules. This is an API class with two modules. One that deals with posting data to the endpoint, and the other that holds functions that are helpers to that post module:

define([
'./Post',
   './Helper'
], function (PostModule, HelperModule) {
    'use strict';
    var module = function () {
        this.Post = new PostModule();
        this.Helper = new HelperModule();
    };
    return module;
});

Now I can chain these modules like this:

var foo = new ApiModule();
foo.Post.postToAPI();
foo.Helper.matchAPIactionToEvent();

which is exactly what I want..

BUT, the problem is within the Post.js file, is that it doesn’t know anything about the Helper.js file. So I can’t take advantage of any of those methods. What I would like to do within the Post.js file is to be able to reference the other functions within the same class like so:

define([
'../environment',
'loglevel',
'../utility/Utility',
'jquery'
], function (EnvironmentModule, log, UtilityModule, $) {
    'use strict';
    var module = function () {
        var environment,
            utility,
            api;

        environment = new EnvironmentModule();
        utility = new UtilityModule();

        this.postToAPI = function (event, payload, callback) {
            var apiEndpoint,
                requestIdString,
                eventAndAction;

            apiEndpoint = environment.getEnvironmentPath().API;
            requestIdString = utility.String.generateRandomString(32);

            /*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/
            eventAndAction = this.Helper.matchAPIactionToEvent(event);
            /*** THIS IS HOW I WANT TO CALL THE HELPER METHODS ***/

            payload.event = eventAndAction.event;
            payload.action = eventAndAction.action;
            payload.requestID = requestIdString;
            payload = $.param(payload);

            $.post(apiEndpoint + '?' + payload, function (result) {
                if (callback) {
                    callback(result);
                }
            });
            return;
        };
    };
return module;
});

I figured out a working solution to the this, where I pass '../api/Helper' as one of the array values in the define statement of Post.js; but I don’t want to do that. What I want is to have Post.js be able to access any method from any other modules that are contained within the same directory. That way I don’t have to explicitly define them. It seems wrong to instantiate a new ApiModule() within Post.js. Here’s the directory structure:

Modules/api/Api.js
Modules/api/Post.js
Modules/api/Helper.js
...

I hope that makes sense. Is this possible?

Matt Kaye
  • 465
  • 1
  • 5
  • 15

1 Answers1

1

Since you want any of the child modules to access any other child modules, what you could do is pass the parent module as an argument to the constructors of the child modules:

var module = function () {
    this.Post = new PostModule(this);
    this.Helper = new HelperModule(this);
};

Have the child modules store this information:

var module = function (parent) {
    this.parent = parent;

Then use this this.parent to call the methods on other child modules:

eventAndAction = this.parent.Helper.matchAPIactionToEvent(event);

Note that if you would load '../api/Helper' with RequireJS in Post.js as you were thinking of doing, you would not be able to use the same object instance as the one defined on the parent module. You'd have to construct a new object for use in Post.js.

Louis
  • 146,715
  • 28
  • 274
  • 320
  • Perfect! That's the exact type of solution I was looking for. Thanks Louis! – Matt Kaye Jan 23 '15 at 14:57
  • Louis, this solution you provided was great, but now I have circular dependencies between these modules. I've read about how to overcome this but i'm not getting anywhere. Based on the solution you gave me here, can you help? Thanks!! – Matt Kaye Jun 09 '15 at 20:52