Saturday, July 11, 2015

Is $scope.$apply() is anti pattern ?

I personally think it’s not anti pattern. As, we know anti pattern implies some technique/ implementation which may solve your current problem but may introduce another big problem for future. So, If we think in this angle $scope.$apply() is not at all harmful or I think there is almost zero chances that it will inject  something wrong in your design flow.

Let’s understand why people use $scope.$apply ! Me too was thinking why to use $scope.$apply ? when AngularJS provides in-built mechanism of model binding ?

Yes, AngularJS has capability of automatic model binding if data comes from AngularJS environment.  If not, then sometimes automatic model binding fails.

From my personal experience I have seen, people are very much handy with $.ajax() function of JQuery to perform AJAX call and this practice may lead you to use $scope.$apply() frequently.  This is one typical situation based on my observation.  So, the core concept is that, If data triggers from non Angular environment then to bind the data to model, we have to trigger $scope.$apply(to execute digest mechanism forcefully) .

Here is one small example where we are using timeout function of JavaScript creates non angular environment.

  setTimeout(function () {
                $scope.message = 'Timeout';
            }, 1000);

This will not work because setTimeout() will try to digest message model after one second but as the mechanism is outside of Angular scope it will not update view with Timeout message.
Now, here is the mechanism to call digest cycle forcefully.

    setTimeout(function () {

                $scope.message = 'Timeout';

               //Call digest cycle forcefully
                $scope.$apply(function () {});
            }, 1000);


Now, one common error you may encounter is “digest already in progress” .This may occur If you try to call digest forcefully within another digest cycle. So, the below code will throw exception surely.

                $scope.$apply(function () {
                    $scope.$apply(function () {
                        $scope.message = "Timeout called!";
                    })
                });

The reason is , we are calling $scope.$apply() within another same.



No comments:

Post a Comment