Make AngularJS skip running a digest loop if $http.get() resulted in no new data

不想你离开。 提交于 2019-11-30 11:48:52

Web sockets would seem to be the most elegant solution here. That way you don't need to poll the server. The server can tell your app when data or anything has changed.

  1. Solution provided by AngularJS @doc

AngularJS recommends to use a PERF trick that would bundle up a few $http responses in one $digest via $httpProvider. This again, is not fixing the problem, it's just a sedative :)

$httpProvider.useApplyAsync(true)

  1. Saving the $$watchers solution - risky and not scalable

Firstly, the accepted solution is not scalable - there's no way you're going to do that $watchers trick on a 100K lines of JS code project - it's out of the question.

Secondly, even if the project is small, it's quite risky! What happens for instance if another ajax call arrives that actually needs those watchers?


  1. Another (feasible) risky solution

The only alternative to achieve this without modifying AngularJS code would be to set the $rootScope.$$phase to true or '$digest', make the $http call, and set back the $rootScope.$$phase to null.

 $rootScope.$$phase = true;
 $http({...})
   .then(successcb, failurecb)
   .finally(function () {
       $rootScope.$$phase = null;            
   });

Risks:

1) other ajax calls might try to do the same thing --> they need to be synchronized via a wrapping ajax service (over $http)

2) user can trigger UI actions in between, actions that will change the $$phase to null and when the ajax call will come back, and still trigger the $digest

The solution popped after scanning AngularJS source code - here's the line that saves the situation: https://github.com/angular/angular.js/blob/e5e0884eaf2a37e4588d917e008e45f5b3ed4479/src/ng/http.js#L1272


  1. The ideal solution

Because this is a problem that everyone is facing with AngularJS, I think it needs to be addressed systematically. The answers above are not fixing the problem, are only trying to avoid it. So we should create a AngularJS pull request that would allow us to specify via $httpProvider a config that would not trigger a digest for a specific $http request. Hopefully they agree that this needs to be addressed somehow.

Thomas Pons

You can do it by this trick :

var watchers;

scope.$on('suspend', function () {
  watchers = scope.$$watchers;
  scope.$$watchers = [];
});

scope.$on('resume', function () {
  scope.$$watchers = watchers;
  watchers = null;
});

With this you will remove your scope or reinsert it on the $digest cycle.

You have to manage events to do that of course.

Refer to this post :

Remove and restore Scope from digest cycles

Hope it helps !

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!