执行一些jQuery.ajax后执行Angular JS代码

时间:2013-01-26 16:47:02

标签: javascript jquery ajax angularjs

我想用一些jQuery ajax调用返回的数据更新Angular范围。我想从Angular外部调用Ajax的原因是:a)我希望调用尽可能快地返回,因此它应该在document.ready之前启动.b)有多个调用初始化多个复杂模型页面网页应用;调用之间有依赖关系,我不想在多个Angular控制器中复制任何逻辑。

这是控制器的一些代码。请注意,代码有些简化以适应此处。

$scope.character = {};
$scope.attributeArray = [];
$scope.skillArray = [];

这样做的原因是角色的属性和技能是对象,但是我使用ng-repeat显示它们,所以我需要它们作为数组。

$scope.$watch('character',function(){
  $scope.attributeArray = getAttributeArray($scope.character);
  $scope.skillArray = getSkillArray($scope.character);
});

理论上,当$ scope.character发生变化时,这段代码会更新两个数组。 现在来了困难的部分。我试过用两种方式更新$ scope.character:

characterRequestNotifier.done(function() { // this is a jQuery deferred object
  $scope.$apply(function(){ // otherwise it's happening outside the Angular world
    $scope.character = CharacterRepository[characterId]; // initialized in the jquery ajax call's return function
  });
});

这有时会导致$digest is already in progress错误。第二个版本使用我写的服务:

repository.getCharacterById($routeParams.characterId, function(character){
  $scope.character = character;
});

,其中

.factory('repository', function(){
  return {
    getCharacterById : function(characterId, successFunction){
      characterRequestNotifier.done(function(){
        successFunction( CharacterRepository[characterId] );
      });
    }
  };
});

这并不总是触发$ watch。

最后,问题是:我怎样才能完成这项任务(没有随机错误,我无法确定其来源)?我的方法是否存在根本性的错误?

编辑:

在这里尝试这个jsfiddle: http://jsfiddle.net/cKPMy/3/ 这是我的代码的简化版本。有趣的是,它不会在延迟解决时触发$ watch。

1 个答案:

答案 0 :(得分:1)

可以通过选中$scope.$$phase来检查是否可以安全地拨打$ apply。如果它返回一些真实的东西 - 例如。 '$apply''$digest' - 将您的代码包装在$apply调用中将导致该错误消息。

就我个人而言,我会选择第二种方法,但使用$q服务 - AngularJS的承诺实施。

.factory('repository', function ($q) {
  return {
    getCharacterById : function (characterId) {
      var deferred = $q.defer();

      characterRequestNotifier.done(function () {
        deferred.resolve(CharacterRepository[characterId]);
      });

      return deferred.promise;
    }
  };
});

由于AngularJS本身支持此承诺实现,因此您可以将代码更改为:

$scope.character = repository.getCharacterById(characterId);

当AJAX调用完成后,承诺得到解决,AngularJS将自动处理绑定,触发$watch等。

添加小提琴后编辑

由于jQuery promise在服务中使用,因此Angular无法知道何时解析了该promise。要修复它,您需要在$apply调用中包装解析。 Updated fiddle。这解决了小提琴,我希望它也能解决你的真正问题。