Why should I wrap a function in the AngularJS $ timeout service without delay, as is the case with the ng-file-upload code example?

In most scripts containing sample usage code for ng-file-upload ( https://github.com/danialfarid/ng-file-upload ), as in ( http://jsfiddle.net/danialfarid/maqbzv15/1118/ ), the load response callback functions complete their code when the $timeout service is called, but these calls do not have a delay parameter passed.

Angular.js docs for $timeout ( https://docs.angularjs.org/api/ng/service/ $ timeout) indicate that a delay is optional, but why you want to make a call to $timeout if you don't delay the code being executed. In other words, instead of the following, why not do the following after:

 //inject angular file upload directives and services. var app = angular.module('fileUpload', ['ngFileUpload']); app.controller('MyCtrl', ['$scope', 'Upload', '$timeout', function ($scope, Upload, $timeout) { $scope.uploadPic = function(file) { file.upload = Upload.upload({ url: 'https://angular-file-upload-cors-srv.appspot.com/upload', data: {username: $scope.username, file: file}, }); file.upload.then(function (response) { $timeout(function () { file.result = response.data; }); }, function (response) { if (response.status > 0) $scope.errorMsg = response.status + ': ' + response.data; }, function (evt) { // Math.min is to fix IE which reports 200% sometimes file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total)); }); } }]); 

Is there any reason for the $timeout shell in all of these examples? Will the following call to file.upload work ?:

 file.upload.then(function (response) { file.result = response.data; }, function (response) { if (response.status > 0) $scope.errorMsg = response.status + ': ' + response.data; }, function (evt) { // Math.min is to fix IE which reports 200% sometimes file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total)); }); 

Edit: I see that it works without the $timeout shell, but the fact that it is included in all the examples makes me think about it intentionally, which probably means there is a case of protection / reliability / compatibility with the browser. I do not understand here.

+5
source share
2 answers

All this has to do with the Angular processing cycle. I will try to demonstrate this with an example before I tell you what a digest cycle is. Provide the following code:

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

There is an inherent problem in this code. Once we change the $scope.name variable after 2 seconds, Angular is completely unaware of this change to $scope.name . If you now consider the following example, which uses $timeout instead of $timeout :

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

Angular will call an anonymous function after two seconds, however then the Angular digest loop will start. This is the main difference between $timeout and setTimeout , a digest cycle loop.

The (simple) Angular digest loop iterates over all observers (bindings), checks for any changes, and re-renders when they fit. You may have seen the mention of $scope.$apply elsewhere - here's how to start a digest cycle.

As for the example you pointed out: if $timeout not used, Angular will not know that any changes have been made, and as such, your view will not be updated. I mentioned $scope.$apply before, so you might be wondering why we are not just using this instead? The problem with using $scope.$apply is that you cannot be sure that the digest loop is no longer running. If you call it while recording, you will see the error message " $digest is already in progress ". $timeout will only work after the current loop and, as such, this error will not be executed.

People often use $timeout without any delay to notify Angular that the change was made by a third party (such as a file loader) that she otherwise did not know what happened.

Hope this clarifies the situation.

Tom

+10
source

$timeout can be used to asynchronously call any callback. eg.

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

This means that all javascript will exit before calling the callback. Adding a delay parameter to the timeout will delay the callback call in about the same way, but you still get asynchronous behavior regardless of whether delay provided.

+1
source

Source: https://habr.com/ru/post/1245399/


All Articles