AngularJS两个Service的self互相覆盖问题技术问询
问题原因分析与解决方案
嘿,这是一个典型的JavaScript作用域陷阱问题!你的两个服务里都直接使用了未声明的self变量,导致它们共享了同一个全局对象,这就是为什么断点时第二个服务的self会被第一个服务的内容填充。
问题本质
在JavaScript中,如果一个变量没有用var/let/const声明,它会被自动提升到全局作用域(浏览器环境下就是window.self)。你的两个服务都在给同一个全局self对象的Model属性赋值,所以第二个服务的self.Model会和第一个服务的Model共享同一个对象,最终两个服务共用同一个self实例。
修复方案
每个服务内部需要声明自己的局部self变量,指向当前服务的单例实例(AngularJS的service基于构造函数模式,this默认指向服务的单例对象)。
修改后的第一个服务代码
(function () { 'use strict'; angular.module('IPortal.Angular.Components.List.Shared.List.Factory', []) .service('listfactory', ['$http', 'loggingService', 'listApiLink', 'listFormRenderService', 'listGridRenderService', function ($http, loggingService, listApiLink, listFormRenderService, listGridRenderService) { // 声明局部self,绑定当前服务实例 var self = this; self.Model = { IsLoadingGrid: false, IsLoadingForm: false, TotalColumns: 0, TotalRows: 0, List:[], ListGrid: [], ListForm: [], ListFormTemplateURL: '', ListGridTemplateURL: '', BaseDate: new Date(), PendingUpdates : [], }; // 注意:原代码递归调用自身会导致无限循环,需替换为实际业务逻辑 self.GetListbyId = function (id, listType) { // 示例:发起HTTP请求获取数据 // return $http.get(`${listApiLink}/lists/${id}?type=${listType}`) // .then(res => { // self.Model.List = res.data; // return self.Model; // }); }; self.GetListDetailbyId = function (id, listType) { // 同理,添加实际的详情获取逻辑 }; self.SaveAnswer = function (pendingQuestion) { var pendingAdd = true; if (self.Model.PendingUpdates.length > 0) { self.Model.PendingUpdates = self.Model.PendingUpdates.filter(function (pendingValue) { if (pendingValue.id === pendingQuestion.id) { pendingAdd = true; return false; } return true; }); } if (pendingAdd) { self.Model.PendingUpdates.push(pendingQuestion); } }; self.Save = function () { var pendingData = self.Model.PendingUpdates; // 添加实际的保存逻辑,比如提交HTTP请求 }; // 暴露服务的公共方法和属性 return { GetListbyId: self.GetListbyId, GetListDetailbyId: self.GetListDetailbyId, SaveAnswer: self.SaveAnswer, Save: self.Save, Model: self.Model }; }]); })();
修改后的第二个服务代码
(function () { 'use strict'; // 注意:RenderForm依赖listFormRenderService,需添加到服务依赖中 angular.module('IPortal.Angular.Components.List.ListForm.InputDirectives.ClinicalOrderStatus.factory', []) .service('clinicalorderstatusfactory', ['$http', 'loggingService', 'listFormRenderService', function ($http, loggingService, listFormRenderService) { var self = this; self.Model = { primaryKey: 0, status : '', statusCode : '', ListFormTemplateURL: '', FormTemplateIsRendered: false }; // 修正原代码拼写错误:UpdataStatus → UpdateStatus self.UpdateStatus = function (primaryKey, patientId, status, reason, accountId) { // 添加实际的更新状态逻辑,比如提交HTTP请求 }; self.RenderForm = function () { self.Model.ListFormTemplateURL = listFormRenderService.Render(self.Model.ListForm); self.Model.FormTemplateIsRendered = true; }; return { UpdateStatus: self.UpdateStatus, Data: self.Model, RenderForm: self.RenderForm }; }]); })();
额外注意事项
- 拼写错误修正:原第二个服务里的
UpdataStatus是拼写错误,改为UpdateStatus后才能正常调用。 - 依赖注入:第二个服务的
RenderForm方法使用了listFormRenderService,必须将其添加到服务的依赖数组中,否则会抛出“undefined”错误。 - 避免无限递归:第一个服务的
GetListbyId原代码递归调用自身,会导致无限循环,必须替换为实际的业务逻辑(比如发起HTTP请求)。
内容的提问来源于stack exchange,提问作者Simon
相关产品推荐
相关产品推荐

