2015-07-01 2 views
3

Примечания: Я использую AngularJS 1,2Angularjs только последний вызов асинхронного в директиве фактически выполняется

У меня есть форма, где каждое поле ударит сервер для проверки на значении изменились.

HTML-фрагмент ниже (Предположим, что для всех целей HTML настроен правильно):



 <div class="col-sm-5"> 
      <input class="form-control input-sm" url="type:googleplus" ng-model="element.googleplus" type="text"><br /> 
      <input class="form-control input-sm" url="type:yelp" ng-model="element.yelp" type="text"><br /> 
      <input class="form-control input-sm" url="type:foursquare" ng-model="element.foursquare" type="text> 
     </div> 

В моей JavaScript я создал директиву, которая перехватывает в каждый и пытается попасть на сервер при обновлении значения. Сценарий, который нарушает текущую функциональность, - это когда форма загружается с заполненными значениями.

OnValueChanged вызывает Validate.Options несколько раз без паузы между ними. Я ожидал, что сервер будет удален для каждого запроса Validation.Options, но вместо этого выполняется только последний вызов.

AngularJS ниже:

... 
.factory('Validation', ['va', function (va) { // 'va' is a throttled resource 
    var result = va('/manage/api/validate?type=:type&input=:url', 
    { 
     type: '@type', 
     url: '@url' 
    }, 
    { 
     options: { 
      method: 'options', 
      debounceMS: 0, // turned off debounce in lieu of this problem 
      abortPending: false 
     } 
    }); 
    return result; 
}]) 

... 
.directive('url', ['$filter', 'Validation', '$q', function ($filter, Validation, $q) { 
    return { 
     require: 'ngModel', 
     link: function (scope, elm, attrs, ctrl) { 
      // parses some stuff 
      var config = {}; 
      (attrs['url'] || '').split(' ').map(function (p) { var a = p.split(':'); config[a[0]] = a[1]; }); 
      if (config.type) 
       config.type = config.type.split(','); 
      config.isRequired = elm[0].required; 

      function validateUrl(viewValue, type) { 
       var deferred = $q.defer(); 
       Validation.options({ url: viewValue, type: type }, function (response) { 
        deferred.resolve(response.IsValid); 
       }); 

       return deferred.promise; 
      } 

      function onValueChanged(viewValue) { 
       // hits the server to check if the url is valid 
       if (viewValue) { 
        var type = config.type ? config.type[0] : undefined; 

        validateUrl(viewValue, type).then(function (isValid) { 
         ctrl.$setValidity('url', isValid); 
        }); 

       } 
       else { 
        // prevents saving the listing as field is invalid 
        ctrl.$setValidity('url', !config.isRequired); 
       } 

       return viewValue; 
      } 

      ctrl.$parsers.push(onValueChanged); 

      // revalidate when the model updates 
      scope.$watch(
       function() { return ctrl.$viewValue; }, 
       function (viewValue) { return onValueChanged(viewValue); } 
      ); 
     } 
    }; 
}]) 

Почему только последний вызов будет выполнен? Открыв вкладку сети, я вижу ровно один серверный вызов с типом «foursquare».

ответ

1

Выяснил это! Имел дело с дросселированным ресурсом ... очевидно, что установка debounceMS на 0 была недостаточной, чтобы предотвратить ее выполнение части debouncing. Я переключился на $ resource, и все сработало (но это также означает, что часть deboucing для onValueChanged не будет работать).