页面偶发数据库数据未加载:寻求替代超时的技术方案
解决页面刷新时偶尔无法获取数据的问题(替代超时方案)
你的问题本质是异步执行时序不匹配——页面有时会在数据请求完成前就完成渲染,而之前用固定101ms超时的方式属于"暴力等待",完全依赖运气,一旦其他功能的执行时序和这个超时冲突,就会导致功能失效。咱们从根源重构代码,用更可靠的方式解决:
第一步:重构数据请求函数,用Promise替代回调
Angular的$http本身就返回Promise,完全没必要用回调模式,改用Promise链式调用能更精准地控制异步流程:
get_data: function (kpi, date_from, date_to) { var config = { method: 'POST', url: '/getData', data: { kpi: kpi, date_from: date_from, date_to: date_to } }; // 直接返回$http的Promise,让上层通过then/catch处理结果 return $http(config) .then(function (response) { return response.data; // 成功时返回数据 }) .catch(function (error) { console.log(error.data, error.status, error.headers, error.config); throw error; // 抛出错误,让上层感知请求失败 }); }
第二步:移除外层$timeout,用Promise链式调用控制渲染时序
原来的外层$timeout是导致其他功能失效的核心——它强制延迟了整个数据请求的发起,打乱了依赖这个函数的其他操作时序。现在我们改为等数据真正返回后再处理页面逻辑:
$scope.update_all_data = function() { $scope.show_loading = true; $scope.display_nodata = false; // 先默认隐藏无数据提示 var date_from = findDateUnix($scope.myDateFrom, $scope.availableDates); var date_to = findDateUnix($scope.myDateTo, $scope.availableDates); // 用Promise的then等待数据返回,确保数据到位后再更新视图 UpdateSvc.get_data($scope.kpi_selected, date_from, date_to) .then(function(res) { raw_data = []; skey_data = []; if(res.raw_data != null && res.raw_data.length > 0){ raw_data = res.raw_data; skey_data = res.skey_data || []; var num = $scope.show_tab.indexOf(true); $scope.filtering = generateCategories(); // 这里的$timeout仅用于等待DOM更新后执行resizeObjects(如果需要的话) $timeout(function(){ $('.md-datepicker-input').prop('disabled', true); resizeObjects(); $scope.show_loading = false; }); } else { $scope.display_nodata = true; $scope.show_loading = false; } }) .catch(function() { // 请求失败时也要关闭loading,避免页面一直处于加载状态 $scope.display_nodata = true; $scope.show_loading = false; }); };
为什么这个方案更可靠?
- 精准的异步控制:不再依赖固定时间的"盲等",而是真正等待数据请求完成后再处理页面,从根源解决"页面先加载、数据未到位"的问题。
- 避免功能冲突:移除外层
$timeout后,update_all_data会立即执行,不会延迟其他依赖该函数的操作,解决之前"大量功能失效"的问题。 - 完善的错误处理:通过
catch统一处理请求失败的场景,确保loading状态一定会被关闭,避免页面卡死。
额外优化建议
- 代码里的
raw_data和skey_data看起来像全局变量,建议改成$scope绑定变量或封装到服务中,避免全局变量污染。 - 操作DOM的
$('.md-datepicker-input').prop('disabled', true)可以用Angular的ng-disabled指令替代(比如在$scope上设datepickerDisabled变量,模板中用ng-disabled="datepickerDisabled"),更符合Angular数据驱动的理念。
内容的提问来源于stack exchange,提问作者Oliver James
相关产品推荐
相关产品推荐

