繁体   English   中英

如何基于Angular中的一个http调用进行多次验证

[英]How to do multiple validations based on one http call in Angular

我在表单上有很多验证字段。

首先,我将其结构化为多个指令,每个指令都有自己的错误消息。

但是,验证使用后端异步调用,因此突然之间,对于一个字段,我对同一数据服务进行了5次http调用。 我正在尝试找出如何更有效地编写此代码。

我想知道是否可以有一个$async验证程序来调用数据服务,并在.then之后的第一个异步函数中有多个常规$validators 我对此进行了实验,但似乎根本无法到达嵌套的$validators

我还尝试在服务中进行一次调用,但是当字段上的modelValue更改时,我不知道如何使它更新,因此将信息传递给相应的验证指令。 我可以将其作为服务中的异步验证并将响应附加到要查找的指令的作用域内吗?

TLDR;

如何进行一次http调用并基于返回的数据执行多次验证检查,每个检查都有自己的错误?

例如

我大约有四个指令,它们看起来都像这样:

angular.module('validationForField').directive('po', ['$q', '$sce', '$timeout', 'myService', function ($q, $sce, $timeout, myService) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl, ngModel) {
            ctrl.$asyncValidators.validateField = function (modelValue) {
                var def = $q.defer();
                myService.httpcall(modelValue)
                    .then(function (response, modelValue) {
                        if (response.data.status === "Error") {  
                            return def.reject();
                        }
                     def.resolve();

                    }).catch(function(){
                    def.reject();
                });
                return def.promise;
            }
        }
    }
}]);

每个数据都有不同的分析,以返回不同的错误消息。 每个调用myService.httpcall都将是多余的,因为它们都获取相同的数据。

我正在尝试做

angular.module('validationForField').directive('po', ['$q', '$sce', '$timeout', 'myService', function ($q, $sce, $timeout, myService) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl, ngModel) {
            ctrl.$asyncValidators.validateField = function (modelValue) {
                var def = $q.defer();
                myService.httpcall(modelValue)
                    .then(function (response, modelValue) {
                        if (response.data.status === "Error") {  
                            return def.reject();
                        }
                        ctrl.$validators.checkStatus = function (response) {
                             if (response.data.data.status === "10"){
                             return false
                         }
                        ctrl.$validators.checkPermissions = function (response) {
                             return response.data.data.permission){

                         }

                     def.resolve();

                    }).catch(function(){
                    def.reject();
                });
                return def.promise;
            }
        }
    }
}]);

这样,主要的异步验证器就可以确定http调用是否成功,以及内部的$ validators在返回数据时使用该数据。

我假设后端服务接受一个值(要验证的字段的值),并为所有验证返回单个响应,例如:

// true would mean valid, string would mean invalid with the given error:
{
    businessRuleOne: true,
    businessRuleTwo: "The format is incorrect",
    ...
}

我相信解决方案是在缓存Promise的服务中执行HTTP调用; 异步验证器调用服务并检索相同的诺言,并返回它们。 一些带有内联说明的示例代码:

// the service:
app.service('myService', function($http, $q) {
    // cache the requests, keyed by the model value
    var requestMap = {};

    this.httpcall = function(modelValue) {
        // if cached, return that (and do not make extra call)
        if( requestMap[modelValue] ) {
            return requestMap[modelValue];
        }
        // if not cahced, make the call...
        var promise = $http.get('....');
        // ...cache it...
        requestMap[modelValue] = promise;
        // ...and remember to remove it from cache when done
        promise.finally(function() {
            delete requestMap[modelValue];
        });
        return promise;
    };
});

现在,异步验证器可以完全按照您发布的方式实现。 调用myService.httpcall(modelValue)将仅在第一个调用时调用远程服务,其余的将重用缓存的myService.httpcall(modelValue)


还有两点:(1)这种技术称为记忆。 它由许多库(例如lodash)实现 ,您可以使用那些库保持myservice.httpcall()干净。 (2)您不需要异步验证程序的额外承诺,例如:

angular.module('validationForField').directive('po', ['$q', '$sce', '$timeout', 'myService', function ($q, $sce, $timeout, myService) {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function (scope, elem, attrs, ctrl, ngModel) {
            ctrl.$asyncValidators.validateField = function (modelValue) {
                return myService.httpcall(modelValue)
                    .then(function (response) {
                        if (response.data.status === "Error") {  
                            return $q.reject();
                        }
                        return response;
                    });
            }
        }
    }
}]);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM