我可以为您翻译。这是一个关于 RequireJS 模块的问题:我能否拥有多个 RequireJS 模块实例?

7
我显然缺少一些概念/理解,特别是JavaScript面向对象的基础知识!
我很喜欢使用RequireJS,我的Web应用现在看起来更像是一个结构化的应用程序,而不是一堆疯狂的代码。
我只是无法理解如何/是否可能实现以下内容。
我有一个名为dataservice_base的模块,它作为基本数据服务模块。
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
    };

});

如您所见,我正在引用dataservices/dataservice,这实际上是核心AJAX调用机制(未显示,但实际上只是在包装器中使用基本的jQuery ajax调用)。

我想做的是允许将该基础dataservice模块“实例化”,如以下代码片段所示(在另一个模块内):

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/');

正如您所见,我试图3次包含同一个(上面定义),但在函数的引用中,我试图通过命名变量引用每个实例,即:
dataservice_profile、dataservice_qualifications、dataservice_subjects
当然,我正在尝试为这些实例设置唯一的值,以便在模块中进一步使用..同时利用通用调用(get,puts,posts等)。
显然,我还缺少一些东西..但是任何帮助让我回到正轨的建议都将非常感激!
敬礼, David.
3个回答

7

我认为您只需要在代码中引入一次所需的依赖项,并使用new关键字。可能您需要重构代码,将常用函数放在一个依赖模块中:

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
    };
});

4

是的,脑冻或者其他类似的问题…有时候独自工作会有这些问题!

正如@asgoth所提到的,我必须清空头脑并仔细思考!

最终,我对数据服务基础模块进行了重构,具体如下:

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;
}

当然,正如@asgoth所提到的,我只需要包含一个对dataservice_base模块的引用,并按照以下方式实例化它以满足我的需求:

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...
}

现在一切都正常工作了!

我想我需要做的唯一另一件事情就是了解如何清理进程以确保这些对象被释放...然而,这将只有很少的几个...但仍然...

再次感谢@asgoth。


3
我曾经对这个概念感到困惑,但这个答案很清晰明了!... 我认为关键在于理解RequireJS始终返回模块的同一个实例,无论你“require”它多少次。然而,如果您的模块返回一个构造函数而不是静态对象,您可以在客户端模块中使用new关键字从构造函数创建实例。每次RequireJS都会返回相同的构造函数,但这正是我们想要的,因为它是一个模板,也就是一个类。客户端模块的工作是从该类创建实例。 - Niko Bellic
1
我想关键在于理解RequireJS始终返回同一模块实例,无论您“require”多少次。 几乎是这样。它确实会缓存第一个所需的实例,但仅当它是完全相同的模块且路径相同时才会缓存。 这意味着,如果您在两个不同的路径(用于应用程序的不同部分)中具有相同的lib“xxx”,例如:app/modules/foo/xxx和app/modules/bar/xxx,则对每个进行要求将带来不同的实例。 如果每个模块都有不同的package.json并且它们请求相同的库,则可能会发生这种情况。 - Hejazzman
1
+1 我在网上寻找示例,展示如何在require.js中以(某种程度上)与C#中使用StructureMap、AutoFac等时DI工作相同的方式工作。直到我看到了你的帖子,我才想到如何注入“单例”vs“瞬态”vs“始终唯一”的依赖实例。 - XDS

2
只需返回一个函数而不是像这样的对象
return function(){
    return {
        // your public interface goes here
    };
}

现在,您可以使用new componentName()创建插件的新实例。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接