为什么我会像在ng-file-upload示例使用代码中那样在没有延迟的情况下在AngularJS $ timeout服务中包装函数?

enc*_*est 5 timeout angularjs ng-file-upload

在大多数样品含有使用码为NG-文件上传的小提琴(的https://github.com/danialfarid/ng-file-upload)之类的一个在(http://jsfiddle.net/danialfarid/maqbzv15/1118 /),上传响应回调函数将其代码包装在$timeout服务调用中,但这些调用没有传入任何延迟参数.

$timeout(https://docs.angularjs.org/api/ng/service/ $ timeout)的Angular.js文档表明延迟是可选的,但是为什么要调用$timeoutif if not not delay code is 跑.换句话说,而不是以下,为什么不在之后做一个:

//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));
});
}
}]);
Run Code Online (Sandbox Code Playgroud)

$timeout在所有这些例子中,包装器有什么理由吗?以下file.upload调用是否可以在其位置工作?:

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));
});
Run Code Online (Sandbox Code Playgroud)

编辑:我可以看到,它似乎没有运行$timeout的包装,但它包含在所有的例子其实让我觉得这是故意的,这可能意味着有一个安全/健壮性/浏览器的兼容性优势的情况下,我不明白这里.

mad*_*kst 11

这与Angular的消化周期有关.在我继续解释摘要周期是什么之前,我将尝试用一个例子来证明这一点.想象一下以下代码:

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

这段代码存在固有的问题.尽管我们$scope.name在2秒后更改了变量,但Angular完全没有意识到这种变化$scope.name.如果您现在考虑我们使用的以下示例$timeout:

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

Angular将在两秒后调用匿名函数,然后,它将从Angular的摘要周期开始.这是$timeoutsetTimeout正在运行的摘要周期之间的主要区别.

摘要周期(简单地说)Angular遍历所有观察者(绑定),检查任何更改并重新呈现适当的位置.您可能已经看到$scope.$apply其他地方的提及- 这是如何开始摘要周期.

关于您提供的示例:如果$timeout未使用,Angular将不会意识到已进行任何更改,因此您的视图将不会更新.我$scope.$apply之前提到过,所以你可能想知道我们为什么不用这个呢?使用的问题$scope.$apply是您无法确定摘要周期是否已在进行中.如果你在一个人发现时调用它,你会看到一个错误" $digest is already in progress".$timeout只会在当前周期之后运行,因此不会发生此错误.

人们经常$timeout毫不迟疑地通知Angular第三方(比如你的文件上传者)已经做出了改变,否则就不会知道发生了什么.

希望这可以解决问题.

汤姆

  • 另外,根据您的需要,您可以考虑使用`$ scope.$ evalAsync()`而不是`$ timeout`.资料来源:https://www.bennadel.com/blog/2605-scope-evalasync-vs-timeout-in-angularjs.htm (2认同)
  • @rinogo我只能想象其他地方的一段代码正在开始摘要周期.除非启动摘要,否则angular不可能知道`$ scope`的更改. (2认同)