AngularJS服务继承问题

我有一个基本服务,看起来像这样:

.service('BaseImageService', ['$q', 'ApiHandler', 'UploadService', function ($q, api, uploadService) {

    // Get our api path
    var apiPath = 'logos';

    // Creates our logo
    var _createLogo = function (model) {

        // Handle our uploads
        return _handleUploads(model).then(function () {

            // Create our logo
            return api.post(apiPath, model);
        });
    };

    // Edit our logo
    var _editLogo = function (model) {

        // Handle our uploads
        return _handleUploads(model).then(function () {

            // Create our logo
            return api.put(apiPath, model);
        });
    };

    // Handles our files
    var _handleUploads = function (model) {

        // Create a promises array
        var promises = [];

        // Get our file
        var file = model.file,
            old = model.old;

        // If we have a file
        if (file) {

            // Try to upload the file
            promises.push(uploadService.upload(model.file).then(function (response) {

                // Update our model
                model.path = response.path;
                model.thumbnail = response.thumbnail;
            }));

            // If we have an old model
            if (old) {

                // Delete both our files
                promises.push(uploadService.delete(old.path));
                promises.push(uploadService.delete(old.thumbnail));
            }
        }

        // After all promises have completed
        return $q.all(promises);
    };

    // Create our service
    var service = {

        // Update our api path
        updateApiPath: function (path) {

            // Set the api path
            apiPath = path;
        },

        // Gets a list of logos
        list: function (t) {

            if (t) {
                console.log(apiPath);
            }

            // Get our logo
            return api.get(apiPath);
        },

        // Get a single logo
        get: function (id) {

            // Get our logo
            return api.get(apiPath, { id: id });
        },

        // Create our logo
        save: function (model) {

            // If we are editing
            if (model.id) {

                // Edit our logo
                return _editLogo(model);

                // If we are creating
            } else {

                // Create our logo
                return _createLogo(model);
            }
        },

        // Deletes our logo
        delete: function (id) {

            // Delete our logo
            return api.delete(apiPath, { id: id });
        },

        // Prepare for editing
        prepareForEditing: function (model) {

            // Create our old object
            model.old = {
                path: model.path,
                thumbnail: model.thumbnail
            };
        }
    };

    // Return our service
    return service;
}])

然后我有一些“继承”这个服务的服务,就像这样:

.service('ImageService', ['BaseImageService', function (baseService) {

    // Get our api path
    var apiPath = 'images';

    // Update the apiPath
    baseService.updateApiPath(apiPath);

    // Return our service
    return baseService;
}])

.service('LogoService', ['BaseImageService', function (baseService) {

    // Get our api path
    var apiPath = 'logos';

    // Update the apiPath
    baseService.updateApiPath(apiPath);

    // Return our service
    return baseService;
}])

.service('PlayerTextService', ['BaseImageService', function (baseService) {

    // Get our api path
    var apiPath = 'playerText';

    // Update the apiPath
    baseService.updateApiPath(apiPath);

    // Return our service
    return baseService;
}])

我认为这工作正常。 但我有这个页面依次调用所有3个服务(ImageService,LogoService和PlayerTextService)。 在页面的第一个视图中,一切都很好,如果我导航离开,然后回来,图像服务实际上会从播放器文本服务中拉回东西。 现在我知道这是因为服务是单身人士,但我不知道如何解决我的问题。

任何人都可以帮我一把吗?


我已经添加了一个尝试解决方案的codepen:

http://codepen.io/r3plica/pen/ONVBJO


尝试2

http://codepen.io/r3plica/pen/jqPeMQ?editors=1010


您尝试的解决方案不起作用,因为BaseService是单身人士。 因此,您将完全相同的实例注入到所有三个服务注册函数中,并且它们都配置相同的对象。 所以基本上最后一个赢了。

看起来你想要有不同配置的单独服务。 这是供应商的用途。 它们允许构建服务实例的两个步骤。 请参阅这个伟大的Stackoverflow在这个话题上的答案:

AngularJS:服务vs供应商vs工厂

作为参考,Restangular是一个库,需要达到完全一样的,你想要的。 你可以用它作为蓝图,看看Restangular如何处理这个需求:

https://github.com/mgonto/restangular#how-to-create-a-restangular-service-with-a-different-configuration-from-the-global-one

请注意,这些概念是基于AngularJS 1的,您需要在稍后想要使用AngularJS 2时以不同的方式处理。


经过很多混乱之后; 我终于找到了适合这一点代码的解决方案

我的基本服务如下所示:

.factory('BaseImageService', ['$q', 'ApiHandler', 'UploadService', 'vectorExtensions', function ($q, api, uploadService, vectorExtensions) {

    // Creates our logo
    var _createLogo = function (model) {

        // Handle our uploads
        return _handleUploads(model).then(function () {

            // Create our logo
            return api.post(BaseImageService.apiPath, model);
        });
    };

    // Edit our logo
    var _editLogo = function (model) {

        // Handle our uploads
        return _handleUploads(model).then(function () {

            // Create our logo
            return api.put(BaseImageService.apiPath, model);
        });
    };

    // Handles our files
    var _handleUploads = function (model) {

        // Create a promises array
        var promises = [];

        // Get our file
        var file = model.file,
            old = model.old;

        // If we have a file
        if (file) {

            // Try to upload the file
            promises.push(uploadService.upload(model.file).then(function (response) {

                // Update our model
                model.path = response.path;
                model.thumbnail = response.thumbnail;
                model.fileName = response.fileName;
            }));

            // If we have an old model
            if (old) {

                // Delete both our files
                promises.push(uploadService.delete(old.path));
                promises.push(uploadService.delete(old.thumbnail));
            }
        }

        // After all promises have completed
        return $q.all(promises);
    };

    // Addes a property to the image array to state if they are vector images or not
    var _addVectorProperties = function (images) {

        // Loop through our images
        for (var i = 0; i < images.length; i++) {

            // Get our current image
            var image = _addVectorProperty(images[i]);
        }

        // Return our images
        return images;
    };

    // Adds a property to the image to state if it is vector or not
    var _addVectorProperty = function (image) {

        // Vector flag
        var vector = false;

        // Get our file extension
        var parts = image.path.split('.');

        // If we have any parts
        if (parts.length) {

            // Get our last part
            var ext = parts[parts.length - 1],
                index = vectorExtensions.indexOf(ext);

            // If our extension exists in our vector array
            if (index > -1) {

                // Change our vector property
                vector = true;
            }
        }

        // Update our image with the new property
        image.vector = vector;

        // Return our image
        return image;
    };

    // Create our service
    var BaseImageService = function (path) {

        // Set our apiPath
        this.apiPath = path;

        // Update our api path
        this.updateApiPath = function (path) {

            // Set the api path
            apiPath = path;
        };

        // Gets a list of logos
        this.list = function () {

            // Get our logo
            return api.get(this.apiPath).then(_addVectorProperties);
        };

        // Get a single logo
        this.get = function (id) {

            // Get our logo
            return api.get(this.apiPath, { id: id }).then(_addVectorProperty);
        };

        // Create our logo
        this.save = function (model) {

            // If we are editing
            if (model.id) {

                // Edit our logo
                return _editLogo(model);

                // If we are creating
            } else {

                // Create our logo
                return _createLogo(model);
            }
        };

        // Deletes our logo
        this.delete = function (id) {

            // Delete our logo
            return api.delete(this.apiPath, { id: id });
        };

        // Set our active image
        this.setActive = function (images, image) {

            // Loop through our images
            for (var i = 0; i < images.length; i++) {

                // Get our current image
                var current = images[i];

                // Set whether we are active or not
                current.active = image.id === current.id ? true : false;
            }
        };

        // Prepare for editing
        this.prepareForEditing = function (model) {

            // Create our old object
            model.old = {
                path: model.path,
                thumbnail: model.thumbnail
            };
        };
    };

    // Return our service
    return BaseImageService;
}])

并且子服务如下所示:

.service('ImageService', ['BaseImageService', function (baseService) {

    // Create our base service
    var child = new baseService('images');

    // Return our new service
    return child;
}])

.service('LogoService', ['BaseImageService', function (baseService) {

    // Create our base service
    var child = new baseService('logos');

    // Return our new service
    return child;
}])

.service('PlayerTextService', ['BaseImageService', function (baseService) {

    // Create our base service
    var child = new baseService('playerText');

    // Return our new service
    return child;
}])

这工作正常。


是的,它是因为它是单身人士而被追加的。 如果你想这样做,你必须执行继承。

这里是我使用并追加到角的代码:

angular.baseResourceServiceMaker = function(service){
    return ['$injector', '$resource', 'TypeService', '$http', '_', 'BackEndpoint', 
        function($injector, $resource,TypeService, $http, _, BackEndpoint){

    //skipping not interesting code 
    // sample fields to inherits
    this.sample = "test";
    this.sampleFN = function(){[...]}
    // THE line that does the magic
    $injector.invoke(service, this);
}

现在是使用时间

.service('MyService',angular.baseResourceServiceMaker(['$http',  function($http){
  // overriding fields
  this.sample="inherits";
 this.sampleFN = function(){[...]}
}]));

那么基本上我们在这里有什么? 表示通用特定服务的函数baseResourceServiceMaker。 调用我们想要实例化的服务的$注入器,并将范围设置为通用服务,因此子类上的这一点将绑定到与泛型类相同的引用。 通用服务将被多次实例化,不会有任何争议。

我个人使用这个代码作为angular的资源模块来定义一些具有自定义序列化器/反序列化器的基本方法,而不是处理日期和其他一些东西。 在你的情况下,baseResourceServiceMaker将作为你的baseImageService以$ injector.invoke(service,this)结尾。

编辑:发现一个可能更干净的东西的链接:AngularJS服务继承

链接地址: http://www.djcxy.com/p/90467.html

上一篇: AngularJS service inheritance issues

下一篇: How do I patch an object so that all methods are mocked except one?