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/maqbzv15/1118/), the upload response callback functions wrap their code in a $timeout
service call, but these calls do not have any delay parameter passed in.
The Angular.js docs for $timeout
(https://docs.angularjs.org/api/ng/service/$timeout) indicate that the delay is optional, but why would you want to make a call to $timeout
if not to delay the code being run. In other words instead of the following, why not do the one 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
wrapper in all these examples? Would the following file.upload call work in its place?:
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 can see that it appears to run without the $timeout
wrapper, but the fact it's included in all the examples makes me think it's deliberate, which probably means there's a security/robustness/browser compatibility edge case I don't understand here.
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With