博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
函数式编程5-对象校验器
阅读量:5844 次
发布时间:2019-06-18

本文共 3361 字,大约阅读时间需要 11 分钟。

对象校验器

本章所有代码,均在

我们来解决一个js的普遍需求。js诞生时,js的作用仅仅一个前端做表单检查的校验器。如今,各种校验框架早已成熟,但是我们仍然有大量的需求需要校验对象。比如后端返回的json我们需要校验,前端提交的json我们需要校验。数据管理中的store我们需要校验,或者说,任意一个函数,我们都需要对入参进行校验。

很多框架或者函数,直接把校验写在写在函数的最顶端。或许有的时候,我们会抽出一个公共函数来校验,比如这样:

const grund = (checker, handle, errorCallback = args => args) => (...args) => {  const result = checker(...args)  if (result.length) {    errorCallback(result)  } else {    return handle(...args)  }}const handle = (...args) => {  console.log('正确处理', args)  return '处理完毕'}const checker = (...args) => !args.length ? ['该函数的参数不能为空'] : []grund(checker, handle, errors => console.log(errors))()复制代码

grund函数用来检验传入参数是否正确,如果正确,执行正确的处理逻辑,如果错误,执行异常处理逻辑。

由于checker过于简单,这并不能满足我们的需求。有时候,我们经常要根据多组条件校验,这就需要多个校验器。而把checker当做数组传入grund显然不是一个好方法。我们需要在checker函数中就传入多组校验器,而checker的工作就是负责把所有校验器合成运行,返回运行结果即可。

const checker = (...validators) => (...args) => {  return validators.reduce((errors, validator) => {    return validator(...args) ? errors : [...errors, validator.message]  }, [])}复制代码

注意这里我们使用了每个校验器的message属性,这似乎是潜规则,没错,这类似于前后端接口的约定字段success,message。几乎所有接口都叫这两个字段(即使不同,也大同小异)。我们调用时候,需要给每个校验器加上message字段。

const validator1 = () => falsevalidator1.message = '校验1不通过'const validator2 = () => falsevalidator2.message = '校验2不通过'checker(validator1, validator2)({})复制代码

好了,效果达成了。可是每个vdalidator都要设置message让人感到痛苦。如果能够自动添加message岂不是更好?我们可以用一个API创建校验器,让人一目了然。

const validator = (handle, message) => {  const fun = (...args) => handle(...args)  fun.message = message  return fun}复制代码

API类似于redux的actionCreator。能让我们轻松创建vilidator。使用时也非常简单。

const v1 = (object) => {  return object.a === 1}const v2 = (object) => {  return object.b === 2}const v3 = (object) => {  return object.c === true}// testconst c1 = checker(validator(v1, 'error1'), validator(v2, 'error2'), validator(v3, 'error3'))复制代码

我们有三个校验规则,v1,v2,v3,通过validator创建了三个校验器传入checker,返回了检查器c1。代码非常清晰明了。

这时候我们开始验证。

const object = {  a: 1,  b: 2,  c: false,}const handle = (...args) => {  console.log('继续处理', args)  return '返回正确'}grund(c1, handle, errors => console.log(errors))(object)// => [ 'error3' ]复制代码

v3要求c属性必须是true,但是测试数据的c属性是false。好,检查器与校验器都能正常工作。可我们如果有这样的需求,需要object里面必须有a,b,c,d四个key,怎么办呢?

添加简单的validator当然没有问题。然而,保持高水平的编码规则需要一些有趣的技巧。高阶函数的本质就是参数可以作为返回函数闭包的行为配置,牢记这一点,可以让你随时随地返回需要函数的地方返回配置过的闭包。

以上面的需求为例。我们再创建一个所需键的简单列表会更加流畅。为了让这个创建列表的函数符合约定,我们让他返回一个闭包和一个错误。

const hasKeys = (...keys) => {  const fun = obj => keys.every(key => obj[key] !== undefined)  fun.message = `object must have value of keys: ${keys}`  return fun}复制代码

你会发现闭包用来检查给的对象是否有效。hasKeys的目的是为了向fun函数提供执行配置。此外,通过直接返回一个函数名,我们很好的描述了需求。从一个函数返回另一个函数的技术,这个过程中捕获参数-被称为柯里化。

使用示例如下:

const c1 = checker(validator(v1, 'error1'), validator(v2, 'error2'), validator(v3, 'error3'), hasKeys('a', 'b', 'c', 'd'))const object = {  a: 1,  b: 2,  c: true,}const handle = (...args) => {  console.log('继续处理', args)  return '返回正确'}grund(c1, handle, errors => console.log(errors))(object)// => [ 'object must have value of keys: a,b,c,d' ]复制代码

当然,我们也可以直接运行c1函数。

const c1 = checker(validator(v1, 'error1'), validator(v2, 'error2'), validator(v3, 'error3'), hasKeys('a', 'b', 'c', 'd'))const object1 = {  a: 1,  b: 2,}const object2 = {  a: 1,  b: 2,  c: true,  d: 1,}console.log(c1(object1))// => [ 'error3', 'object must have value of keys: a,b,c,d' ]console.log(c1(object2))// => []复制代码

在任何情况下,使用c1检查器构建语法一致性,也就是说,在校验器固定的情况下,检查器会按照校验器所定义的方式校验,我们只需要传入需要校验的参数即可。

转载地址:http://rnqcx.baihongyu.com/

你可能感兴趣的文章
【SpringBoot】在IOC之外的类中使用IOC内部的Bean
查看>>
android--Activity有返回值的跳转
查看>>
Fiddle:使用断点:bpu,bpafter
查看>>
一个js的动画,以前以为只有flash可以实现
查看>>
使用onclick跳转到其他页面。使用button跳转到指定url
查看>>
CentOS搭建Sqoop环境
查看>>
suse linux ssh远程无法访问问题
查看>>
HDU 5673 Robot 卡特兰数
查看>>
只显示标准采购订单
查看>>
只允许操作外协任务
查看>>
Python--day60--一个简单(不完整)的web框架
查看>>
一些服务器编程的概念
查看>>
scjp jdk1.5 ——4.19(6)
查看>>
iOS开发之打包上传报错: ERROR ITMS-90087/ERROR ITMS-90125
查看>>
一些PHP函数功能
查看>>
HDU5248:序列变换(二分)
查看>>
JS 事件练习
查看>>
thymeleaf th:href url传递多参数
查看>>
统计学习方法概论---分类问题
查看>>
强制类型转换问题
查看>>