AngularJS FileReader和$ scope的问题.$ watch?

Jim*_*zie 1 javascript filereader angularjs

我有一个奇怪的(对我来说至少),希望有人能够提供帮助.也许我只是在考虑这个错误的方式或者其他什么.尝试使用javascript中的文件对我来说是全新的.

我有一个指令,其模板如下所示:

<input type="file" ng-file-select ng-model="files">
<button ng-click="onFileSelect()">Upload</button>
Run Code Online (Sandbox Code Playgroud)

在指令的控制器中,我这样做:

$scope.onFileSelect = function() {
  reader = new FileReader();
  reader.onload = function() {
    $scope.file_contents = this.result;
  };
  reader.readAsArrayBuffer($scope.files[0]);

//debugger;
  $scope.$watch('file_contents',function(file_contents) {
    console.log(file_contents);
    if (angular.isDefined(file_contents)) {
      ... bunch of code attempting to deal with file_contents ...
    }
  });
};
Run Code Online (Sandbox Code Playgroud)

我选择一个文件,然后单击"上传"按钮.(file_contents)的console.log未定义.只有当我第二次点击按钮时,它才有值.

如果我取消注释调试器,$ scope.file_contents在我检查它时会有一个值.

因此,file_contents需要一些时间来设置(这是预期的),但$ watch似乎从未注意到?这有什么奇怪的原因吗?$ watch无法使用FileReader对象吗?

编辑1:

好的.这是一些更多的信息.根据PSL的建议,我现在有了这样的代码:

$scope.onFileSelect = function() {
  reader = new FileReader();
  reader.onload = function() {
    file_contents = this.result;
    upload_file($scope.files[0],file_contents);
  };
   reader.readAsArrayBuffer($scope.files[0]);
};

upload_file = function(file,file_contents) {
  <lots of cool file_contents-y stuff>
};
Run Code Online (Sandbox Code Playgroud)

为什么我仍然得到$ digest错误?我已经没有$ watch了.我没有对upload_file中的$ scope做任何事情.$ digest错误中没有堆栈跟踪来帮助我.我得到的只是:

Error: [$rootScope:inprog] $digest already in progress
http://errors.angularjs.org/1.3.0-beta.10/$rootScope/inprog?p0=%24digest
Run Code Online (Sandbox Code Playgroud)

这是做什么的?

PSL*_*PSL 5

Watch似乎永远不会注意到因为您正在更新角度上下文之外的范围.您需要使用scope.$apply()或在任何其他方式(例如在onload异步函数中使用$ timeout等)手动调用摘要循环.并且最好将手表移到onFileSelect方法之外,否则你将继续观看每次上传点击.

尝试:

$scope.onFileSelect = function() {
  reader = new FileReader();
  reader.onload = function() {
    $scope.file_contents = this.result;
    $scope.$apply(); /<-- here
  };
  reader.readAsArrayBuffer($scope.files[0]);

};

$scope.$watch('file_contents',function(file_contents) {
    console.log(file_contents);
    if (angular.isDefined(file_contents)) {
      ... bunch of code attempting to deal with file_contents ...
    }
});
Run Code Online (Sandbox Code Playgroud)

不确定完整的场景,但你可能甚至不需要创建一个手表只是将文件处理包装在一个方法中并从中调用该方法onload并执行一个范围.$ apply().你的手表第一次执行的原因是因为它一旦设置就会一直运行以启动脏检查,到那时async onload没有在范围上设置任何值,即使它确实设置了摘要周期也不是意识到这一点.