Angularjs是指令中实际执行的最后一个异步调用

Angularjs only last async call in directive actually executed

本文关键字:最后一个 异步 调用 执行 指令 Angularjs      更新时间:2023-09-26

注意:我使用的是AngularJS 1.2

我有一个表单,其中每个字段都将在值更改时到达服务器进行验证。

下面的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"的服务器调用。

想明白了!与被抑制的资源有关。。。显然,将去抖动MS设置为0不足以阻止它执行去抖动部分。我切换回$resource,一切都正常(但这也意味着onValueChanged的去粘部分不起作用(。