How can I create an angular JS service that isn

2019-07-06 21:14发布

Because every service is a singleton. & calling $injector.get() still gives me the same instance everytime.

How can I use multiple instances of a service inside another service? Keeping in mind that the declaration of my non-singleton class, must not pollute the global namespace etc.

My example is below: (Where I wanted $injector.get('serviceCall') to be a different instance everytime, but I've since discovered it can't be.

app.factory('reportsService', ['$injector', function ($injector) {
    var o = {};
    o.getServiceCall = function () {
        return $injector.get('serviceCall');
    };
    o.getOriginCompositionData = function (ajaxOptions) {
        ajaxOptions.url = '/test/SpiderRequestOriginComposition';
        o.getServiceCall().initialize(ajaxOptions);
    };
    o.getExeuctionTimeData = function (ajaxOptions) {
        ajaxOptions.url = '/test/SpiderRequestExeuctionTime';
        o.getServiceCall().initialize(ajaxOptions);
    };
    o.getCacheCompositionData = function (ajaxOptions) {
        ajaxOptions.url = '/test/SpiderRequestCacheComposition';
        o.getServiceCall().initialize(ajaxOptions);
    };
    return o;
}]);

and my serviceCall Service:

app.factory('serviceCall', function () {
    var o = {};
    o.initialize = function (userOptions) {
        o.options = o.getOptions(userOptions);
        o.call();
    };
    o.getOptions = function (userOptions) {
        var defaultOptions = {
            action: 'post',
            url: '', //userOptions
            successCallback: '', //userOptions
            errorCallback: '', //userOptions
            dataType: 'json'
        };
        var options = $.extend(defaultOptions, userOptions);
        return options;
    };
    o.call = function () {
        $.ajax({
            type: o.options.action,
            url: o.options.url,
            data: o.options.data,
            success: function (r) {
                o.options.successCallback(r);
            },
            error: function (xhr, textStatus, errorThrown) {
                //TODO
            },
            dataType: o.options.dataType,
            contentType: o.options.contentType
        });
    };
    return o;
});

2条回答
家丑人穷心不美
2楼-- · 2019-07-06 21:27

You'll need to implement the factory pattern. Return a service that creates object instances for you. $injector.get('serviceCall') will always return a singleton, but there's nothing stopping you making that singleton's job generating new object instances for you.

Rather than using $injector, directly DI a serviceCallFactory service, and call methods on that to generate the new serviceCall instances.

查看更多
一纸荒年 Trace。
3楼-- · 2019-07-06 21:37

Agree with @eddiec.

The thing is, when you're new to angular, you suppose factory is like the design pattern Factory : a function that provides a new instance at each call. However, 'factory' in angular is actually a function that is called only one time and that returns an object that will be "cached". Now, every time you DI with the factory name, this object will be injected, not the factory function.

So, if you want a "real" (the design pattern) Factory, you need to create a function that returns a new object.

Here is a quick implementation

app.factory('serviceCallFactory', function () {

    function o() {
        var o = {};
        o.initialize = function (userOptions) {
            o.options = o.getOptions(userOptions);
            o.call();
        };
        o.getOptions = function (userOptions) {
            var defaultOptions = {
                action: 'post',
                url: '', //userOptions
                successCallback: '', //userOptions
                errorCallback: '', //userOptions
                dataType: 'json'
            };
            var options = $.extend(defaultOptions, userOptions);
            return options;
        };
        o.call = function () {
            $.ajax({
                type: o.options.action,
                url: o.options.url,
                data: o.options.data,
                success: function (r) {
                    o.options.successCallback(r);
                },
                error: function (xhr, textStatus, errorThrown) {
                    //TODO
                },
                dataType: o.options.dataType,
                contentType: o.options.contentType
            });
        };
        return o;
    }

    return {
        create : function () {
            return new o();
        }
    }

});


app.factory('reportsService', ['serviceCallFactory', function (serviceCallFactory) {
    var o = {};
    o.getServiceCall = function () {
        return serviceCallFactory.create();
    };
    o.getOriginCompositionData = function (ajaxOptions) {
        ajaxOptions.url = '/test/SpiderRequestOriginComposition';
        o.getServiceCall().initialize(ajaxOptions);
    };
    o.getExeuctionTimeData = function (ajaxOptions) {
        ajaxOptions.url = '/test/SpiderRequestExeuctionTime';
        o.getServiceCall().initialize(ajaxOptions);
    };
    o.getCacheCompositionData = function (ajaxOptions) {
        ajaxOptions.url = '/test/SpiderRequestCacheComposition';
        o.getServiceCall().initialize(ajaxOptions);
    };
    return o;
}]);
查看更多
登录 后发表回答