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?