1

I have an Angular app which sometimes has large collections in the scope. This means the digest is sometimes very slow. I have 257 watches which I don't think is all that much. Rendering is done with React. This apparent unresponsiveness would be ok if I could indicate to the user that the app was busy.

I have tried to place a div centrally as the indicator and set this to happen using a $watch as described in the Angular docs: https://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch

The trouble is there is a noticeable 2-3 second pause before anything seems to happen. After this pause the div is displayed, the digest completes and the React rendering runs which hides the div on completion. I can test this consistently by using a debounced text box bound to a model to cause a digest cycle. It seems as though when some intensive JS runs the browser forgets all attempts to update the window - I even see the animated gifs stop in this 2-3 second timeframe.

I've tested in Chrome and Firefox both on Windows 7 so far.

Is there a better way to show some kind of indicator to the user? Clearly I'm barking up the wrong tree here.

Robin Elvin
  • 1,207
  • 12
  • 28
  • Not possible. JavaScript runs in essentially a single-threaded execution environment - the browser is in fact "frozen". If it was an async operation, then it's a different story. From experience, no amount of "busy" indicators would help if the entire window is frozen while some processing is going on. You can't offload it to some worker thread. You ought to see how to reduce the processing happening during each digest - are you sure that you don't have a watch on a function that does something heavy? – New Dev Feb 27 '15 at 17:25
  • You could call a function that shows or hides an overlay based on '$scope.$$phase'. So the overlay is thrown up, the watches are called on a 200ms timeout and then as soon as the browser can it checks $scope.$$phase and removes the overlay. Check out this answer http://stackoverflow.com/questions/12729122/prevent-error-digest-already-in-progress-when-calling-scope-apply – Rorschach120 Feb 27 '15 at 17:37
  • '
    ' Where detectDigest() would return true or false depending on $scope.$$phase.
    – Rorschach120 Feb 27 '15 at 17:38
  • It seems it is related to the size of the collection in the scope. Collections under 200 objects render very quickly but over that amount it seems to take a long while to run the digest. I think the answer is to refactor and get the collection out of the scope. The scope is used to pass props to React (using ngReact) but I think I'll write my own render method and pass props directly. – Robin Elvin Mar 05 '15 at 16:43

0 Answers0