Angular: $ resource update запускает запрос PUT только при втором вызове

У меня есть ресурс с настраиваемым методом обновления:

angular.module('user.resources', ['ngResource']).
factory('User', function($resource) {
  var User = $resource('/user/:id', {}, {
    update: {
      method: 'PUT'
    }
  });

  User.prototype.update = function(cb) {
    console.log('foo');
    return User.update({
      id: this._id
    }, angular.extend({}, this, {
      _id: undefined
    }), cb);
  };

Я передаю этот ресурс специальной директиве через область видимости:

directive('avatarUpload', function($http) {
  return {
    restrict: 'E',
    scope: {
      model: '='
    }, ...

и я вызываю метод обновления в контроллере директив при щелчке btn:

$scope.model.update(function() {
  console.log('bar');
});

Поведение, которое меня озадачивает, заключается в том, что при первом нажатии на кнопку выводится «foo», но не «bar», при втором нажатии на кнопку выводится «bar», а затем «foo». Если больше щелкнуть, всегда печатайте «bar», затем «foo».

Запрос PUT запускается только при втором щелчке и последующих, а не при первом.

Примечание. Я отлично использовал этот метод обновления ресурсов в контроллерах, пока не попытался вызвать его из директивы. Я использую angular 1.1.4. Я передаю этот ресурс, потому что хочу, чтобы директива работала с другим типом ресурса.


person plus-    schedule 21.06.2013    source источник


Ответы (1)


Трудно сказать наверняка, не увидев пример живого кода, но я предполагаю, что вы используете AngularJS из серии 1.1.x (так называемая «нестабильная ветвь»). Если это так, проблема, с которой вы столкнулись, связана с новой функцией AngularJS - перехватчиками HTTP-запросов, представленными в версии 1.1.4 (this совершить).

Недавно представленные перехватчики запросов основаны на $q (основаны на обещаниях), а в мире AngularJS обещания разрешаются только как часть цикла $digest. Другими словами, вы должны находиться в «мире AngularJS» ($digest цикл), чтобы обещания были выполнены.

С перехватчиками запросов на основе обещаний есть обещание, которое должно быть разрешено до того, как будет сделан $http вызов. Как отмечалось ранее, это обещание может быть выполнено только тогда, когда вы войдете в цикл $digest. Этого не произойдет, если вы запускаете $http извне AngularJS (событие DOM, setTimeout и т. Д.).

В AngularJS $resource основан на $http, поэтому приведенное выше обсуждение применимо и к $resource.

Итак, предполагая, что приведенные выше предположения верны и вы инициируете вызов $resource извне AngularJS (вы говорите о настраиваемой директиве, поэтому я бы сделал ставку на событие DOM) вы должны просто обернуть вызов $resource в scope.$apply < / сильный>.

Обратите внимание, что перенос вызова $resource в $timeout (как предлагается в другом ответе), while «исправит» вашу проблему (вызовет цикл $ digest и, таким образом, обещания будут решены) это неправильный подход . Проблема в том, что это заставит браузер покинуть текущий контекст JavaScript и впустую войти в контекст перерисовки. Это замедлит работу вашего приложения и может привести к мерцанию пользовательского интерфейса.

person pkozlowski.opensource    schedule 24.06.2013