首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >民间故事的嵌套验证

民间故事的嵌套验证
EN

Stack Overflow用户
提问于 2018-01-09 18:16:02
回答 1查看 129关注 0票数 0

我在一个新项目中使用了民间故事验证,我发现它非常有用,但我遇到了需要顺序验证的问题。我有一个配置对象,需要执行以下验证:

  • 是物体吗?
  • 对象的键有效吗(它们是否出现在白名单上)?
  • 键的值有效吗?

每个验证都取决于先前的验证--如果项不是对象,验证其键是没有意义的(并且会出错),如果对象没有键,则验证它们的值是没有意义的。如果验证失败,我想有效地进行短路验证。

我最初的想法是使用结果,而不是在其他地方定义和使用validateIsObject`。

我目前(正在工作但很难看)的解决方案如下:

代码语言:javascript
复制
import { validation } from 'folktale';
import { validateIsObject } from 'folktale-validations';
import validateConfigKeys from './validateConfigKeys';
import validateConfigValues from './validateConfigValues';

const { Success, Failure } = validation;

export default config => {
  const wasObject = validateIsObject(config);
  let errorMessages;
  if (Success.hasInstance(wasObject)) {
    const hadValidKeys = validateConfigKeys(config);
    if (Success.hasInstance(hadValidKeys)) {
      const hasValidValues = validateConfigValues(config);
      if (Success.hasInstance(hasValidValues)) {
        return Success(config);
      }
      errorMessages = hasValidValues.value;
    } else {
      errorMessages = hadValidKeys.value;
    }
  } else {
    errorMessages = wasObject.value;
  }
  return Failure(errorMessages);
};

我最初采用了使用嵌套matchWith的方法,但这甚至更难理解。

如何改进这个解决方案?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-10 16:34:46

您可以编写一个应用验证规则的助手,直到返回Failure为止。一个简单的例子:

代码语言:javascript
复制
const validateUntilFailure = (rules) => (x) => rules.reduce(
  (result, rule) => Success.hasInstance(result) 
    ? result.concat(rule(x)) 
    : result,
  Success()
);

我们使用concat将两个结果结合起来。我们使用Success.hasInstance来检查是否需要应用下一个规则。您的模块现在将有一行长:

代码语言:javascript
复制
export default config => validateUntilFailure([ 
  validateIsObject, validateConfigKeys, validateConfigValues
]);

注意,这个实现在看到Failure后不会提前返回。递归实现可能是更实用的方法,但并不是每个人都喜欢:

代码语言:javascript
复制
const validateUntilFailure = ([rule, ...rules], x, result = Success()) => 
  Failure.hasInstance(result) || !rule
    ? result
    : validateUntilFailure(rules, x, result.concat(rule(x)))

有关运行代码,请参阅下面的示例。有一节注释掉了,显示了如何运行所有规则,即使有失败。

代码语言:javascript
复制
const { Success, Failure } = folktale.validation;

const validateIsObject = (x) =>
  x !== null && x.constructor === Object
  	? Success(x)
	  : Failure(['Input is not an object']);

const validateHasRightKeys = (x) =>
  ["a", "b"].every(k => k in x) 
  	?  Success(x)
		:  Failure(['Item does not have a & b.']);

const validateHasRightValues = (x) =>
  x.a < x.b
  	? Success(x)
		: Failure(['b is larger or equal to a']);


// This doesn't work because it calls all validations on
// every item
/*
const validateItem = (x) =>
  Success().concat(validateIsObject(x))
           .concat(validateHasRightKeys(x))
           .concat(validateHasRightValues(x))
           .map(_ => x);
*/

// General validate until failure function:
const validateUntilFailure = (rules) => (x) => rules.reduce(
  (result, rule) => Success.hasInstance(result) 
    ? result.concat(rule(x)) 
    : result,
  Success()
);

// Let's try it out!
const testCases = [
  null,
  { a: 1 },
  { b: 2 },
  { a: 1, b: 2 },
  { a: 2, b: 1 }
];

const fullValidation = validateUntilFailure([
	validateIsObject, 
  validateHasRightKeys,
  validateHasRightValues
]);



console.log(
  testCases
    .map(x => [x, fullValidation(x)])
    .map(stringifyResult)
    .join("\n")
);

function stringifyResult([input, output]) {
  return `input: ${JSON.stringify(input)}, ${Success.hasInstance(output) ? "success:" : "error:"} ${JSON.stringify(output.value)}`;
}
代码语言:javascript
复制
<script src="https://cdnjs.cloudflare.com/ajax/libs/folktale/2.0.1/folktale.min.js"></script>

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48174364

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档