注册信息校验问题
用户输入的注册信息需要在前端进行数据校验后才能提交给后端,而校验操作存在一定的顺序,如果在一个函数中使用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'
}7
收起
正在回答 回答被采纳积分+1
1回答
恭喜解决一个难题,获得1积分~
来为老师/同学的回答评分吧
0 星