如何根据 Angular 中的一次 http 调用进行多次验证
How to do multiple validations based on one http call in Angular
我在表单上有一个字段需要大量验证。
起初,我将它构造成多个指令,每个指令都有自己的错误消息。
但是,验证使用后端异步调用,所以突然间我为一个字段对同一个数据服务进行了 5 个 http 调用。我想弄清楚如何更有效地编写它。
我想知道是否可以在 .then
之后的第一个异步函数中有一个 $async
调用数据服务的验证器和多个常规 $validators
。我对此进行了试验,但它似乎根本没有到达嵌套的 $validators
。
我也尝试在服务中调用一次,但我不知道如何在字段上的 modelValue 更改时更新它,从而将信息传递给相应的验证指令。我可以将此作为服务中的异步验证来执行,并将响应附加到要查找的指令的范围吗?
TLDR;
如何进行一次 http 调用并根据 returned 数据执行多项验证检查,每项检查都有自己的错误?
例如
我有大约四个指令都是这样的:
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;
}
}
}
}]);
每个人对数据的分析不同,导致return不同的错误信息。每个人都调用 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 调用是否成功的主要异步验证器,以及在 returns
时使用该数据的内部 $validators
我假设后端服务接受一个值(要验证的字段的值)并且 return 是对所有验证的单一响应,例如:
// true would mean valid, string would mean invalid with the given error:
{
businessRuleOne: true,
businessRuleTwo: "The format is incorrect",
...
}
我认为解决方案是在缓存承诺的服务中执行 HTTP 调用;异步验证器调用该服务并检索相同的承诺,他们 return。一些带有内联解释的示例代码:
// 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;
};
});
现在可以像您一样实现异步验证器 post。调用 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;
});
}
}
}
}]);
我在表单上有一个字段需要大量验证。
起初,我将它构造成多个指令,每个指令都有自己的错误消息。
但是,验证使用后端异步调用,所以突然间我为一个字段对同一个数据服务进行了 5 个 http 调用。我想弄清楚如何更有效地编写它。
我想知道是否可以在 .then
之后的第一个异步函数中有一个 $async
调用数据服务的验证器和多个常规 $validators
。我对此进行了试验,但它似乎根本没有到达嵌套的 $validators
。
我也尝试在服务中调用一次,但我不知道如何在字段上的 modelValue 更改时更新它,从而将信息传递给相应的验证指令。我可以将此作为服务中的异步验证来执行,并将响应附加到要查找的指令的范围吗?
TLDR;
如何进行一次 http 调用并根据 returned 数据执行多项验证检查,每项检查都有自己的错误?
例如
我有大约四个指令都是这样的:
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;
}
}
}
}]);
每个人对数据的分析不同,导致return不同的错误信息。每个人都调用 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 调用是否成功的主要异步验证器,以及在 returns
时使用该数据的内部 $validators我假设后端服务接受一个值(要验证的字段的值)并且 return 是对所有验证的单一响应,例如:
// true would mean valid, string would mean invalid with the given error:
{
businessRuleOne: true,
businessRuleTwo: "The format is incorrect",
...
}
我认为解决方案是在缓存承诺的服务中执行 HTTP 调用;异步验证器调用该服务并检索相同的承诺,他们 return。一些带有内联解释的示例代码:
// 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;
};
});
现在可以像您一样实现异步验证器 post。调用 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;
});
}
}
}
}]);