AngularJS工厂嵌套使用问题:依赖注入后值为undefined
咱们一步步拆解你代码里的问题,看看为什么eqInfoFactory.eqInfo会返回undefined:
1. 依赖注入顺序完全错了!
在lastInspectionDetail这个Factory的定义里,你忽略了AngularJS的核心依赖注入规则——注入数组里的字符串顺序必须和函数参数的顺序完全对应。
你原来的代码是这样的:
eqDetail.factory('lastInspectionDetail', ['eqInfoFactory', function($http, eqInfoFactory) { // ... }]);
这里注入数组只写了eqInfoFactory,但函数第一个参数是$http,第二个才是eqInfoFactory。AngularJS会按数组顺序把依赖传给参数,结果就是$http参数实际拿到的是eqInfoFactory,而eqInfoFactory参数变成了undefined,你访问eqInfoFactory.eqInfo当然会出问题!
修正方法:
把需要的依赖都写到数组里,顺序和参数一一对应:
eqDetail.factory('lastInspectionDetail', ['$http', 'eqInfoFactory', function($http, eqInfoFactory) { // ... }]);
2. 异步数据的时机没处理好
你两个Factory里都是立即执行了数据获取函数(getEqInfo()和getInsInfo()),但$http是异步请求啊!当lastInspectionDetail初始化的时候,eqInfoFactory里的API请求可能还没返回,eqInfoFactory.eqInfo还没被赋值,自然就是undefined。
AngularJS里处理异步数据,必须用Promise(巧了,$http本身就返回Promise),我们得调整Factory的结构,让它们提供获取数据的方法,而不是直接返回还没拿到的结果。
修正后的完整代码示例
var eqDetail = angular.module('eqDetail', []); eqDetail.config(['$locationProvider', function($locationProvider) { $locationProvider.html5Mode({ enabled: true, requireBase: false }); }]); // 第一个Factory:改成返回获取数据的方法,用Promise处理异步 eqDetail.factory('eqInfoFactory', function($location, $http) { var cachedEqInfo = null; // 缓存数据,避免重复请求 return { getEqInfo: function() { // 如果已经拿到过数据,直接返回缓存的结果 if (cachedEqInfo) { return Promise.resolve(cachedEqInfo); } // 发起异步API请求 return $http.get('你的设备信息API地址') .then(function(response) { // 这里写你的数据清洗逻辑 var sanitizedData = /* 处理response.data的代码 */ response.data; cachedEqInfo = sanitizedData; // 缓存结果 return cachedEqInfo; }) .catch(function(error) { console.error('获取设备信息失败:', error); throw error; // 把错误抛出去,让调用者处理 }); } }; }); // 第二个Factory:等待第一个Factory的异步请求完成后再获取数据 eqDetail.factory('lastInspectionDetail', ['$http', 'eqInfoFactory', function($http, eqInfoFactory) { var cachedInsInfo = null; return { getInsInfo: function() { if (cachedInsInfo) { return Promise.resolve(cachedInsInfo); } // 先等设备信息拿到手,再发起检查信息的请求 return eqInfoFactory.getEqInfo() .then(function(eqData) { // 用设备信息作为参数请求检查数据 return $http.get('你的检查信息API地址', { params: { eqId: eqData.id } // 这里替换成你实际需要的参数 }) .then(function(response) { var sanitizedInsData = /* 处理检查数据的代码 */ response.data; cachedInsInfo = sanitizedInsData; return cachedInsInfo; }); }) .catch(function(error) { console.error('获取检查信息失败:', error); throw error; }); } }; }]); // 控制器里通过Promise的then方法获取异步数据 eqDetail.controller('eqInfo', function($scope, eqInfoFactory) { $scope.eq = {}; eqInfoFactory.getEqInfo() .then(function(eqData) { $scope.eq = eqData; console.log($scope.eq); }); }); eqDetail.controller('inspectionResult', function($scope, lastInspectionDetail) { $scope.insResult = {}; lastInspectionDetail.getInsInfo() .then(function(insData) { $scope.insResult = insData; console.log($scope.insResult); }); });
几个关键的优化点
- 依赖注入顺序严格匹配:记住AngularJS的注入是按位置匹配的,数组里的每个字符串都要对应函数里的参数顺序。
- 用Promise处理异步:不再直接返回未完成的异步结果,而是提供方法让调用者等待请求完成。
- 数据缓存:在Factory里缓存已经获取的数据,避免重复发起API请求,提升性能。
这样调整后,lastInspectionDetail会等eqInfoFactory拿到有效的设备数据后再发起自己的请求,就不会出现undefined的问题了。
内容的提问来源于stack exchange,提问作者morteza kiaee

