Dav.id
Dav.id

Reputation: 2797

Can I have multiple instances of a RequireJS Module?

I am obviously missing some concept/understanding and most definitely javascript OO basics!

I am loving using RequireJS, and my web app now looks more like a structured app now rather than a whole heap of crazy code.

I am just struggling to understand how/if the following is possible.

I have a module which acts as a base dataservice module called dataservice_base as follows:

define(['dataservices/dataservice'], function (dataservice) {

    // Private:     Route URL
    this.route = '/api/route-not-set/';
    var setRoute = function (setRoute) {
        this.route = setRoute;
        return;
    }

    //  Private:    Return route with/without id 
    var routeUrl = function (route, id) {
        console.log('** Setting route to: ' + route);
        return route + (id || "")
    }

    //  Private:    Returns all entities for given route
    getAllEntities = function (callbacks) {
        return dataservice.ajaxRequest('get', routeUrl())
        .done(callbacks.success)
        .fail(callbacks.error)
    };

    getEntitiesById = function (id, callbacks) {
        return dataservice.ajaxRequest('get', routeUrl(this.route, id))
        .done(callbacks.success)
        .fail(callbacks.error)
    };

    putEntity = function (id, data, callbacks) {
        return dataservice.ajaxRequest('put', routeUrl(this.route, id), data)
        .done(callbacks.success)
        .fail(callbacks.error)
    };

    postEntity = function (data, callbacks) {
        return dataservice.ajaxRequest('post', routeUrl(this.route), data)
        .done(callbacks.success)
        .fail(callbacks.error)
    };

    deleteEntity = function (id, data, callbacks) {
        return dataservice.ajaxRequest('delete', routeUrl(this.route, id), data)
        .done(callbacks.success)
        .fail(callbacks.error)
    };

    //  Public:     Return public interface
    return {
        setRoute: setRoute,
        getAllEntities: getAllEntities,
        getEntitiesById: getEntitiesById,
        putEntity: putEntity,
        postEntity: postEntity,
        deleteEntity: deleteEntity
    };

});

As you can see, I am referencing dataservices/dataservice, which is actually the core AJAX call mechanism (not shown, but really just basic jQuery ajax call in a wrapper).

What I am trying to do is allow this base dataservice module to be "instanced" as follows (within another module - snippet code only):

define(['dataservices/dataservice_base', 'dataservices/dataservice_base', 'dataservices/dataservice_base'], function (dataservice_profile, dataservice_qualifications, dataservice_subjects) {

    //  Set the service route(s)
    dataservice_profile.setRoute('/api/profile/');
    dataservice_qualifications.setRoute('/api/qualification/');
    dataservice_subjects.setRoute('/api/subject/');

As you can see, I am trying to include the same dataservice_base(defined above) 3 times, but in the function references, I am trying to refer to each instance by named vars i.e:

dataservice_profile, dataservice_qualifications, dataservice_subjects

.. and of course I am trying be able to set a unique setRoute value for each of those instances to use further on in the module.. whilst leveraging the common calls (get,puts,posts etc).

Obviously I am missing a few things here.. but any help to point me back on the road would be very gratefully received!!

Kind Regards, David.

Upvotes: 7

Views: 6669

Answers (3)

dude
dude

Reputation: 6086

Just return a function instead of a object like this

return function(){
    return {
        // your public interface goes here
    };
}

Now you can create new instances of your plugin with new componentName().

Upvotes: 2

Dav.id
Dav.id

Reputation: 2797

Yes, brain-freeze or whatever.. problems of working alone sometimes!

So, as @asgoth mentioned, quite rightly had to clear my mind and think things through a bit!

I ended up with a re-factored dataservice_base module as follows:

define(['dataservices/dataservice'], function (dataservice) {

    //  Set any class/static vars

    //  Set the instance function
    function dataservice_base(setRoute) {

        var self = this;

        self.route = setRoute;
        console.log('setting route: ' + self.route);

        function routeUrl(route, id) {
            console.log('** Setting route to: ' + route);
            return route + (id || "")
        }

        self.getAllEntities = function (callbacks) {
            return dataservice.ajaxRequest('get', routeUrl())
            .done(callbacks.success)
            .fail(callbacks.error)
        }

        self.getEntitiesById = function (id, callbacks) {
            return dataservice.ajaxRequest('get', routeUrl(self.route, id))
            .done(callbacks.success)
            .fail(callbacks.error)
        }

        self.putEntity = function (id, data, callbacks) {
            return dataservice.ajaxRequest('put', routeUrl(self.route, id), data)
            .done(callbacks.success)
            .fail(callbacks.error)
        }

        self.postEntity = function (data, callbacks) {
            return dataservice.ajaxRequest('post', routeUrl(self.route), data)
            .done(callbacks.success)
            .fail(callbacks.error)
        }

        self.deleteEntity = function (id, data, callbacks) {
            return dataservice.ajaxRequest('delete', routeUrl(self.route, id), data)
            .done(callbacks.success)
            .fail(callbacks.error)
        }

    } // eof instance

    return dataservice_base;
}

and of course again as @asgoth mentioned, I only need to of course include one reference to the dataservice_base module, and instance it for my needs as follows:

define(['dataservices/dataservice_base','viewmodels/viewmodel_profile', 'viewmodels/viewmodel_qualifications', 'viewmodels/viewmodel_subjects', 'app/common'], function (dataservice_base, viewmodel_profile, viewmodel_qualifications, viewmodel_subjects, common) {

    var dataservice_profile = new dataservice_base('/api/profile/');
    var dataservice_qualifications = new dataservice_base('/api/qualification/');
    var dataservice_subjects = new dataservice_base('/api/subject/');

    // do whatever now with those instance objects...
}

SO.. now all working!

I guess the only other thing I need to do is looking up about cleaning up process to ensure these objects are released.. however there will only ever be a few.. but still..

thanks again @asgoth

Upvotes: 4

asgoth
asgoth

Reputation: 35829

I think you need to include your dependency only once and use the new keyword. Possibly you will need to refactor so that the common functions are in a depending module:

define(['dataservices/dataservice'], function (dataservice) {
    var dataservice_profile = new dataservice();
    var dataservice_qualifications = new dataservice();
    var dataservice_subjects = new dataservice();

    //  Set the service route(s)
    dataservice_profile.setRoute('/api/profile/');
    dataservice_qualifications.setRoute('/api/qualification/');
    dataservice_subjects.setRoute('/api/subject/');

    // define needs to return something
    return {
       profile: dataservice_profile,
       qualifications: dataservice_qualifications,
       subjects: dataservice_subjects
    };
});

Upvotes: 7

Related Questions