【发布时间】:2015-05-20 19:42:34
【问题描述】:
我有一个长时间运行的任务,我想显示一个简单的 div 来提醒用户并让他们等待。
我有一个自定义过滤器需要大约 10 秒才能应用。这大约是初始页面加载时间的三倍,因此仅此一项就是一个问题,但如果我可以显示一个警告他们任务正在内存中工作的 div,我的用户会在某种程度上感到满意。
我正在使用 ng-show="filteringTasks" 变量,但它没有显示 div,因为 Angular 似乎正忙于过滤过程并且用户界面没有更新。
<div ng-show="filteringTasks">Filtering Tasks...Please wait </div>
所有任务都是在页面初始加载时加载的,因此在这种情况下,“数据”是数据库中的所有 400 多条记录。这是 ng-repeat 的 html:
<div ng-repeat="task in filteredTasks =
( data | filter:searchText | statusFilter:statusOptions
orderBy:predicate:reverse ) track by task.id "
on-finish-render="ngRepeatFinished">
ng-repeat 完成时会触发指令“ngRepeatFinished”。这工作正常。
过滤器正在为每个任务寻找五个状态(过滤器数组)中的一个或多个。如果 task.status 与请求的状态匹配并且过滤器为真,则将任务添加到结果中。
这是过滤器:
ppApp.filter('statusFilter', [ function ( $filter ) {
return function( input, filter ) {
if ( input ) {
var result = [];
angular.forEach(input, function ( task ) {
angular.forEach( filter, function( ans, status ) {
if ( task.status == status && ans ) {
result.push( task );
}
});
});
return result;
}
};
}]);
最后,为了提示用户,我在控制器中添加了这个:
$scope.initialPageLoad=true;
$scope.$watch("statusOptions['incomplete']", function() {
if ( $scope.initialPageLoad ) {
$scope.initialPageLoad = false;
} else {
alert('this may take a while');
$scope.filteringTasks=true;
}
});
这个概念是提醒用户注意长时间运行的任务并通过设置 $scope.filteringTasks=true; 来显示 div;一种想法是实现无限滚动指令并在完成时显示结果。另一个是有某种进度条,但如果界面甚至不显示一个简单的 div 似乎就没有用了!我真的不知道为什么过滤器需要这么长时间才能应用,但代码会正确触发。
我怎样才能可靠地让用户知道 ng-repeat 在幕后工作?
【问题讨论】:
-
您的 ng-repeat 在 ng_show 之后仍然不显示“过滤任务?”
-
没错。 div 仅在一切完成之前显示一毫秒。它在 ng-repeat 工作时不显示。
-
我知道这不是问题,但您确实提到您不知道为什么运行需要这么长时间,因此仅使用标准 for 循环可能值得重写。它应该更快:jsperf.com/angular-foreach-vs-native-for-loop/3,这里是原生/jQuery 测试:jsperf.com/for-vs-foreach/37。
-
我修改了过滤器以使用本机 forEach 并显式迭代过滤器对象。我没有发现性能有很大的提高,但这个想法是有效的。
-
在 ng-repeat 中使用 "bind once" 提高效率有意义吗?如果是这样,有人可以告诉我如何正确地做到这一点。我将 ng-repeat 修改为: task in ::filteredTasks 但这似乎不起作用。似乎这可以通过将性能提高到我不需要显示 div 来过滤数据的程度来解决问题。
标签: javascript angularjs