Show loading animation for slowscript using AngularJS?

前端 未结 8 556
野的像风
野的像风 2020-12-24 12:08

In angularjs 1.2 operations like filtering an ng-repeat with many rows (>2,000 rows) can become quite slow (>1 sec).
I know I can optimize execution times u

8条回答
  •  我在风中等你
    2020-12-24 12:36

    The problem is that as long as Javascript is executing, the UI gets no chance to update. Even if you present a spinner before filtering, it will appear "frozen" as long as Angular is busy.

    A way to overcome this is to filter in chunks and, if more data are available, filter again after a small $timeout. The timeout gives the UI thread a chance to run and display changes and animations.

    A fiddle demonstrating the principle is here.

    It does not use Angular's filters (they are synchronous). Instead it filters the data array with the following function:

    function filter() {
        var i=0, filtered = [];
        innerFilter();
    
        function innerFilter() {
            var counter;
            for( counter=0; i < $scope.data.length && counter < 5; counter++, i++ ) {
                /////////////////////////////////////////////////////////
                // REAL FILTER LOGIC; BETTER SPLIT TO ANOTHER FUNCTION //
                if( $scope.data[i].indexOf($scope.filter) >= 0 ) {
                    filtered.push($scope.data[i]);
                }
                /////////////////////////////////////////////////////////
            }
            if( i === $scope.data.length ) {
                $scope.filteredData = filtered;
                $scope.filtering = false;
            }
            else {
                $timeout(innerFilter, 10);
            }
        }
    }
    

    It requires 2 support variables: $scope.filtering is true when the filter is active, giving us the chance to display the spinner and disable the input; $scope.filteredData receives the result of the filter.

    There are 3 hidden parameters:

    • the chunk size (counter < 5) is small on purpose to demonstrate the effect
    • the timeout delay ($timeout(innerFilter, 10)) should be small, but enough to give the UI thread some time to be responsive
    • the actual filter logic, which should probably be a callback in real life scenarios.

    This is only a proof of concept; I would suggest refactoring it (to a directive probably) for real use.

提交回复
热议问题