angularjs - 为什么我会像在 ng-file-upload 示例使用代码中那样在 AngularJS $timeout 服务中包装一个函数,而不会延迟?

标签 angularjs timeout ng-file-upload

在大多数包含 ng-file-upload ( https://github.com/danialfarid/ng-file-upload ) 示例使用代码的 fiddle 中,例如 ( http://jsfiddle.net/danialfarid/maqbzv15/1118/ ),上传响应回调函数将其代码包装在 $timeout 中。服务调用,但这些调用没有传入任何延迟参数。
$timeout 的 Angular.js 文档( https://docs.angularjs.org/api/ng/service/ $timeout) 表示延迟是可选的,但为什么要调用 $timeout如果不是为了延迟正在运行的代码。换句话说,为什么不做下面的,而不是下面的:

//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));
});
}
}]);
$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));
});

编辑:我可以看到它似乎在没有 $timeout 的情况下运行wrapper,但它包含在所有示例中的事实让我认为这是故意的,这可能意味着存在我在这里不理解的安全/健壮性/浏览器兼容性边缘情况。

最佳答案

这一切都与 Angular 的摘要循环有关。在继续解释什么是摘要循环之前,我将尝试通过一个示例来证明这一点。想象一下下面的代码:

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

这段代码有一个固有的问题。就像我们改变 $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);
}]);

Angular 将在两秒后调用匿名函数,然而,它将开始 Angular 的摘要循环。这是 $timeout 之间的主要区别。和 setTimeout ,正在运行的摘要循环。

摘要循环是(简单地说)Angular遍历所有观察者(绑定(bind)),检查任何更改并在适当的地方重新渲染。您可能已经看到对 $scope.$apply 的提及其他地方 - 这是如何开始消化周期。

关于您提供的示例:如果 $timeout没有使用,Angular 不会意识到已经进行了任何更改,因此您的 View 不会更新。我提到了$scope.$apply早些时候,所以您可能想知道为什么我们不直接使用它?使用 $scope.$apply 的问题是您无法确定摘要周期尚未进行。如果你在一个发生时调用它,你会看到一个错误“$digest is already in progress”。 $timeout只会在当前周期之后运行,因此不会发生此错误。

人们经常使用$timeout毫不拖延地通知 Angular 第三方(例如您的文件上传者)已进行了更改,否则它不会知道发生了更改。

希望这可以解决问题。

汤姆

关于angularjs - 为什么我会像在 ng-file-upload 示例使用代码中那样在 AngularJS $timeout 服务中包装一个函数,而不会延迟?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36108158/

相关文章:

javascript - Angular 模态 : add buttons from button list

javascript - 解析 ng-show 时出现 Angular 错误

java - Java耗时过长如何成功销毁进程?

angularjs - 如何在 AngularJS 中预览上传的文件

javascript - 在 Cloudinary 中使用 ngf-resize 上传图像

angularjs - 如何使用 Protractor 检查元素是否可见?

javascript - AngularJS 在 ng-repeat 循环中保留临时值

mysql - 如何根据 MySQL 中的用户登录设置连接超时

mysql - 如何让 golang mysql 驱动程序在 2 秒内超时 ping?

javascript - 无法使用 Angular.js ng-file-upload 替换文件名