注册信息校验问题

注册信息校验问题

用户输入的注册信息需要在前端进行数据校验后才能提交给后端,而校验操作存在一定的顺序,如果在一个函数中使用if-else这样的选择逻辑,会导致代码混乱,后期难维护的后果。

针对这个问题,我使用了两种方法进行了实现。

  • 第一种借助了JavaScript内置的promise。

  • 第二种借助了函数式编程的概念

我认为第一种方式语义化更好,通过then表示数据校验操作的步骤,但对每个校验操作创建Promise似乎有小题大做,希望老师能够评价一下这两种方法的优劣。如果可以的话,能否说一下这两种方法还有哪些地方可以改进?

同时第二种方式需要传入successHandler,这会使调用变得繁琐,如果把successHandler改为()->{},只返回校验信息,如下所示,调用时只需传入data,但又会使()->{}难以理解,老师有没有办法能够去除这里的()->{},但依旧能够实现功能?

function checkerAll (...validators) {
  const funcChain = validators.map(validator => next => data => {
    if (!validator(data)) return validator.message
    return next(data)
  })
  return compose(...funcChain)(()->{})
}

下面是Promise方法实现的代码

function hasEmptyAttr (obj) {
  return Object.values(obj).some(value => value === '')
}
function validator(predict,message) {
  return data => new Promise((resolve, reject) => {
    if (predict(data)) {
      resolve(data)
    }
    reject(new Error(message))
  })
}
function emptyCheck (data) {
  return !hasEmptyAttr(data)
}
function confirmSame (data) {
  return data.password === data.confirm
}
async function submitData (data) {
  try {
    await register({ username: data.username, password: data.password })
  } catch (err) {
    return Promise.reject(new Error(getErrorMessage(err)))
  }
}
const registerClick = () => {
    const data = activeToObj(form)
    validator(emptyCheck,'has empty input')(data)
      .then(validator(confirmSame,'password not correspond'))
      .then(submitData)
      .then(successRegister)
      .catch(err => { registerInfo.value = err.message })
}

下面是函数式实现的方式

function compose (...fns) {
  return fns.reduce((fn1, fn2) => {
    return (...args) => {
      return fn1(fn2(...args))
    }
  })
}
/**
 * 如果校验函数从左到右依次对data进行校验,如果校验错误返回message
 * @param  {...any} validators 校验函数
 * @returns function 接收成功回调函数
 */
function checkerAll (...validators) {
  const funcChain = validators.map(validator => next => async data => {
    if (!validator(data)) return validator.message
    return await next(data)
  })
  return successHandler => {
    if (typeof successHandler !== 'function') throw Error('successHandler must be function')
    return compose(...funcChain)(successHandler)
  }
}

/**
 * 将谓词函数转变为验证函数
 * @param {string} message 错误消息
 * @param {function} fun 谓词函数
 * @returns function
 */
function validator (message, fun) {
  const f = (...args) => {
    return fun.apply(fun, args)
  }
  f.message = message
  return f
}
async function submitData (data) {
  try {
    await register({ username: data.username, password: data.password })
  } catch (err) {
    return Promise.reject(new Error(getErrorMessage(err)))
  }
}
function emptyCheck (data) {
  return !hasEmptyAttr(data)
}
function passwordConfirmCheck (data) {
  return data.password === data.confirm
}
const message = checkerAll(validator('has empty input', emptyCheck), validator('password not correspond', passwordConfirmCheck))(async data => {
      try {
        await submitData(data)
        return successHandler()
      } catch (err) {
        return err
      }
    })(data)
message.then(info => {
      registerInfo.value = info
    })
function successHandler () {
    setTimeout(() => {
      router.push({ name: 'Login' })
    }, 1000)
    return 'success to register'
  }


正在回答 回答被采纳积分+1

登陆购买课程后可参与讨论,去登陆

1回答
好帮手慕然然 2021-10-18 17:18:06

同学你好,这两种实现方式都挺好,第一种使用promise实现更易于理解,代码执行过程清晰易懂,关于每个校验操作都要创建Promise对象的问题,其实也可以利用then方法依次执行校验,而不用每次都调用validator方法创建Promise对象。

第二种实现方式比较复杂,代码比较绕,没有第一种容易理解,关于successHandler回调函数的处理,个人觉得按照同学封装的代码,将successHandler改为()->{}是没问题的。

祝学习愉快!

问题已解决,确定采纳
还有疑问,暂不采纳

恭喜解决一个难题,获得1积分~

来为老师/同学的回答评分吧

0 星
请稍等 ...
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号

在线咨询

领取优惠

免费试听

领取大纲

扫描二维码,添加
你的专属老师