Why would I wrap a function in AngularJS $timeout service without a delay like they do in ng-file-upload example usage code?

前端 未结 2 1301
旧时难觅i
旧时难觅i 2020-12-18 06:16

In most of the fiddles containing sample usage code for ng-file-upload (https://github.com/danialfarid/ng-file-upload) like the one at (http://jsfiddle.net/danialfarid/maqbz

相关标签:
2条回答
  • 2020-12-18 07:02

    It's all to do with Angular's digest cycle. I'll try to demonstrate this with an example before I go on to explain what the digest cycle is. Imagine the following code:

    angular.module('app', []).controller('TestController', ['$scope', function($scope){
        $scope.name = 'Tom';
        setTimeout(function(){
            $scope.name = 'Bob';
        }, 2000);
    }]);
    

    There's an inherent problem with this code. As much as we change the variable of $scope.name after 2 seconds, Angular is completely unaware of this change to $scope.name. If you now consider the following example where we use $timeout instead:

    angular.module('app', []).controller('TestController', ['$scope', '$timeout', function($scope, $timeout){
        $scope.name = 'Tom';
        $timeout(function(){
            $scope.name = 'Bob';
        }, 2000);
    }]);
    

    Angular will call the anonymous function after two seconds, however, it will then start off Angular's digest cycle. This is the main difference between $timeout and setTimeout, the digest cycle being run.

    The digest cycle is (put simply) Angular going over all of the watchers (bindings), checking for any changes and re-rendering where appropiate. You may have seen a mention to $scope.$apply elsewhere - this is how to start the digest cycle.

    With regards to the example you provided: If the $timeout wasn't used, Angular wouldn't be aware that any changes have been made and as such, your view wouldn't update. I mentioned $scope.$apply earlier so you may be wondering why we don't just use this instead? The problem with using $scope.$apply is that you cannot be sure that a digest cycle isn't in progress already. If you do call it while one is occcuring, you'll see an error "$digest is already in progress". $timeout will only run after the current cycle and as such, this error won't happen.

    People often use $timeout without any delay to notify Angular that a change has been made by a third party (like your file uploader), that it otherwise wouldn't know had happened.

    Hopefully this clears things up.

    Tom

    0 讨论(0)
  • 2020-12-18 07:03

    $timeout can be used to invoke any callback asynchronously. e.g.

    $timeout(function callback() {
      // code run asynchronously...
    });
    

    This means that all javascript will finish running before your callback is invoked. Adding a delay parameter to the timeout will delay the callback invocation approximately that much further, but you still gain asynchronous behavior whether or not a delay is provided.

    0 讨论(0)
提交回复
热议问题