问题
Is there a pattern in Angular apps for computation-heavy tasks? (Beyond just using $timeout with a delay of 0 to let them get off the call stack?) Even using $timeout seems to make the UI unresponsive when the processing itself kicks in. Do I need to be looking at Web Workers or something like that, or is there an "Angular way?"
回答1:
Because JavaScript is single threaded, you need to either do the computations server-side, or do the timeouts in between the processing (See underscore's defer(), http://underscorejs.org/#defer). Otherwise, the UI will inevitably get blocked.
回答2:
I came up with a way to solve my UI responsiveness problem by creating special loop functions that use an Angular $timeout each time through the loop.
app.service('responsivenessService', function($q, $timeout) {
var self = this;
// Works like Underscore's map() except it uses setTimeout between each loop iteration
// to try to keep the UI as responsive as possible
self.responsiveMap = function(collection, evalFn)
{
var deferred = $q.defer();
// Closures to track the resulting collection as it's built and the iteration index
var resultCollection = [], index = 0;
function enQueueNext() {
$timeout(function () {
// Process the element at "index"
resultCollection.push(evalFn(collection[index]));
index++;
if (index < collection.length)
enQueueNext();
else
{
// We're done; resolve the promise
deferred.resolve(resultCollection);
}
}, 0);
}
// Start off the process
enQueueNext();
return deferred.promise;
}
return self;
});
This mapping function returns a promise which can be assignable to a $scope. Usage is similar to the map() functions from Underscore or native Javascript arrays in newer browsers:
$scope.results = responsivenessService.responsiveMap(initialdata, function() {
// Long-running or computationally intense code here
return result;
});
Code that would originally have blocked the whole UI now appears to run in the background (although essentially it's an illusion, like calling Application.DoEvents periodically in older applications). Nice and generic, as long as the long-running code is conducive to a looping map()-style operation!
来源:https://stackoverflow.com/questions/17299715/angularjs-computation-heavy-tasks