如何在 Javascript 中使用 Ramda 将此嵌套 if 函数转换为函数式编程

How can I turn this nested if function into functional style programming with Ramda in Javascript

我正在查看 Prisma 中用于软删除中间件的代码:

  prisma.$use(async (params, next) => {
    // Check incoming query type
    if (params.model == 'Post') {
      if (params.action == 'delete') {
        // Delete queries
        // Change action to an update
        params.action = 'update'
        params.args['data'] = { deleted: true }
      }
      if (params.action == 'deleteMany') {
        // Delete many queries
        params.action = 'updateMany'
        if (params.args.data != undefined) {
          params.args.data['deleted'] = true
        } else {
          params.args['data'] = { deleted: true }
        }
      }
    }
    return next(params)
  })

它的步骤是: 检查 Post -> 如果它是 'delete' 或 'deleteMany' 然后将操作更改为 'update' 并将 deleted 设置为 true.

嵌套的 if 似乎不太理想,而且使用函数式风格似乎会更干净,所以我使用 Ramda 来尝试让它发挥作用:

const model = lensProp('model')
const action = lensProp('action')
const argsData = compose(lensProp('args'), lensProp('data'))
const cView = curry(view)
const modelView = cView(model)
const actionView = cView(action)
const _shouldBeModified = (models, actions, p) => and(
    includes(modelView(p), models),
    includes(actionView(p), actions)  
)
const shouldBeModified = curry(_shouldBeModified)
const timeElapsed = Date.now();
const today = new Date(timeElapsed);

const softDelete = (models, actions, params) => ifElse(
  shouldBeModified(models, actions), 
  pipe(
    set(argsData, { deleted: true, deletedAt: today.toISOString()}), 
    set(action, 'update')
  ),
  identity
)(params)

然后我可以这样称呼它:

softDelete(['Post'],['delete', 'deleteMany'],params)

/*
 returns: {"action": "update", "args": {"data": {"deleted": true, "deletedAt": "2022-04-17T19:49:00.294Z"}}, "model": "Post"}
*/

综上所述,我是 Ramda 的新手,我的方法似乎很乱,有人可以帮我清理一下吗?

您可以使用 R.whenR.where 来检查 params 是否应该更新。如果是这样,请使用 R.evolve 更新它们。

传递一个 actions 对象,而不是一个数组,因此代码可以根据原始操作映射 update / updateMany

const { curry, when, where, includes, __, keys, evolve, prop, mergeDeepLeft } = R

const actionsMap = { delete: 'update', deleteMany: 'updateMany' };

const softDelete = curry((models, actions, params) => when(
  where({
    model: includes(__, models),
    action: includes(__, keys(actions))
  }),
  evolve({
    action: prop(__, actions),
    args: mergeDeepLeft({ data: { deleted: true, deletedAt: new Date().toISOString() }})
  })
)(params))

const params = {"action": "deleteMany", "args": { data: { something: 5 } }, "model": "Post"}

const result = softDelete(['Post'], actionsMap, params)

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/ramda/0.28.0/ramda.min.js" integrity="sha512-t0vPcE8ynwIFovsylwUuLPIbdhDj6fav2prN9fEu/VYBupsmrmk9x43Hvnt+Mgn2h5YPSJOk7PMo9zIeGedD1A==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>