Сбой привязки Angular Service к Scope после обновления 1.2

Я попытался убрать детали и сделать это довольно обобщенно...

Используя 1.2 rc2, мой код работал нормально, после обновления до стабильной версии 1.2 и исправления изменений $parse я столкнулся с проблемой привязки. До обновления следующий код работал без проблем. updateChildObject() вызывается с html-страницы.

.when('/the-page/', {
  controller: function($scope, serviceResults, FactoryService) {
    $scope.object.childObject = serviceResults;

    // this function used to work. Now assigns the function to the 
    // scope rather than the results
    $scope.updateChildObject = function(args) {
      $scope.object.childObject = FactoryService.getSomethingFromServer(args);
    };

  },
  resolve: {
    serviceResults: function(FactoryService) {
      return FactoryService.getSomethingFromServer(args);
    }
  }

Поскольку сейчас это не удается ($scope.object.childObject, кажется, устанавливается как функция, а не результаты), я считаю, что подходящий способ решить эту проблему - через обещание. (Обратите внимание, что сама служба успешно использует обещание.) Однако у меня возникают трудности с обновлением $scope, когда обещание разрешено.

Я считаю, что следующий код находится на правильном пути. $q вводится в контроллер.

...
$scope.updateChildObject = function(args) {
  var defer = $q.defer();
  defer.promise.then(function() {
    return FactoryService.getSomethingFromServer(args);
  });
  $scope.object.childObject = defer.resolve();
};
...

Так может ли кто-нибудь сказать мне, что я делаю неправильно здесь? Обещания — это всего лишь одна из тех вещей, которые мне еще не очень понравились.


person iamsar    schedule 12.11.2013    source источник


Ответы (2)


В качестве альтернативы вашему ответу: вы говорите, что FactoryService уже успешно использует обещание, и в этом случае кажется, что вам не нужно дополнительное обещание и в updateChildObject. Вы можете обновить FactoryService.getSomethingFromServer(args), чтобы вернуть обещание (то есть с return defer.promise; в конце и defer.resolve(results); в асинхронном бите), а затем упростить updateChildObject до простого:

$scope.updateChildObject = function(args) {
  FactoryService.getSomethingFromServer(args).then(function(results) {
     $scope.object.childObject = results;
  }
};

Кроме того, стоит знать, что Angular 1.2 намеренно нарушает автоматическую развертку промисов, которая была в более ранних версиях: https://github.com/angular/angular.js/issues/4158 . Раньше было так, что этот код

$scope.updateChildObject = function(args) {
     $scope.object.childObject = FactoryService.getSomethingFromServer(args);
};

будет работать так же, как и выше (при условии, что getSomethingFromServer возвращает обещание), но не больше. Возможно, это проблема, с которой вы столкнулись в версии 1.2.

person Michael Low    schedule 12.11.2013
comment
Ах, чувак, спасибо за подсказку. Понятия не имею, что я мог бы использовать мой сервис, как это. Действительно полезно. Таким образом, обе версии работают одинаково хорошо. Ваша модель устраняет необходимость вводить $q, что мне нравится. Хотя вы правы, автоматическая распаковка была именно тем, к чему я стремился. - person iamsar; 12.11.2013

Разобрался, что я делаю не так. Определенно, это была проблема с обещаниями, потому что я просто не использовал их правильно. Следующее решило это:

...
$scope.updateChildObject = function(args) {
    var defer = $q.defer();
    defer.promise.then(function(results) {
        $scope.object.childObject = results;
    });
    defer.resolve(FactoryService.getSomethingFromServer(args));
};
...

Итак, defer.resolve вызывает то, что должно быть разрешено. promise.then() передает результаты следующему действию. Так просто.

person iamsar    schedule 12.11.2013