AngularJS 1.6.6中Cannot read property 'length' of undefined问题排查
解决AngularJS异步请求导致下拉列表填充报错的问题
你遇到的核心问题是异步请求的执行顺序没有控制好,导致onCourses函数运行时,$scope.Courses还没从服务器拿到数据(还是undefined),这时候访问$scope.Courses.length就会触发报错。
问题根源分析
看你的控制器代码,这三个异步请求是并行发起的:
CourseService.getCourseClasses(IdSessionCourse).then(...); CourseService.getCurrentSessionCourses().then(function (courses) { $scope.Courses = courses }); CourseService.courses().then(onCourses);
JavaScript的异步操作不会等待前一个完成再执行下一个,所以onCourses很可能在getCurrentSessionCourses返回数据、给$scope.Courses赋值之前就运行了,这时候$scope.Courses是undefined,自然会报错。
解决方案:控制异步请求的执行顺序
我们需要确保$scope.Courses已经被赋值后,再执行CourseService.courses().then(onCourses),把后续逻辑嵌套到getCurrentSessionCourses的回调里即可:
修改后的AddStudentController.js代码:
(function(){ var myApp = angular.module("myApp"); var AddStudentController = function ($scope, StudentService, CourseService) { var onCourses = function (data) { var result = []; // 此时$scope.Courses已经被成功赋值,不会是undefined for (var i = 0; i < $scope.Courses.length; i++) { for (var j = 0; j < data.length; j++) { if (data[j].IdCourse === $scope.Courses[i].idCourse) { if (result.indexOf(data[j]) === -1) { result.push(data[j]); } } } } $scope.courses = result; // 增加空值判断,避免result为空时selectedCourse是undefined if (result.length > 0) { $scope.selectedCourse = result[0]; var IdCourse = $scope.selectedCourse.IdCourse; // 用find简化查找逻辑(如果你的环境支持ES6) var matchedCourse = $scope.Courses.find(course => course.idCourse === IdCourse); var IdSessionCourse = matchedCourse ? matchedCourse.idSessionCourse : null; if (IdSessionCourse) { CourseService.getCourseClasses(IdSessionCourse).then(function (classes) { $scope.classes = classes; $scope.selectedClass = classes.length > 0 ? classes[0] : undefined; }); } } }; // 先获取CurrentSessionCourses,拿到数据后再执行后续逻辑 CourseService.getCurrentSessionCourses().then(function (courses) { $scope.Courses = courses; // 确保$scope.Courses存在后,再调用courses()并处理结果 CourseService.courses().then(onCourses); }); }; myApp.controller("AddStudentController", AddStudentController) }());
额外优化建议
- 增加空值安全判断:在访问数组元素或对象属性前,先检查是否存在,避免因空数据导致的报错。
- 简化数组操作:用
find、filter等数组方法替代嵌套for循环,让代码更简洁可读(如果你的AngularJS环境支持ES6语法)。 - HTML下拉列表优化:给select标签添加默认空选项,提升用户体验:
<!-- 第一个下拉列表 --> <select ng-model="selectedCourse" ng-change="change()" class="form-control" ng-options="course.IdCourse as course.Name for course in courses"> <option value="">-- 选择课程 --</option> </select> <!-- 第二个下拉列表 --> <select ng-model="selectedClass" class="form-control" ng-options="class.idClass as class.className +' : '+class.campusName for class in classes"> <option value="">-- 选择班级 --</option> </select>
这样调整后,就能保证第一个下拉列表的填充逻辑在数据准备好之后执行,彻底解决异步请求导致的undefined报错问题。
内容的提问来源于stack exchange,提问作者Junaid Farooq
相关产品推荐
相关产品推荐

