【问题标题】:Call nested methods on object only if it exists using Ramda仅当使用 Ramda 存在时才在对象上调用嵌套方法
【发布时间】:2016-11-30 22:02:25
【问题描述】:

我目前有一个user 对象,它上面有一个currentRoom() 方法,它有时可能不存在或返回null

如果currentRoom() 方法返回了一些东西,那么我需要调用messages() 方法。如果两者都没有返回,我想返回一个默认的空数组[]

我想使用 Ramda 在功能上解决这个问题,所以它简洁且可重复使用。目前,我的(非 Ramda)代码如下所示:

const user = Users.findOne({ username: params.id })
const room = (user.currentRoom && user.currentRoom() || {})
const messages = (room.messages && room.messages() || [])

我想的某种逻辑是传入所需方法的列表,如果没有任何结果,则连同默认结果一起传递。

/* getMessages(defaultIfNull, methodsArray, object) */

getMessages([], ['currentRoom', 'messages'], user)

基本上有点类似于pathOr,但针对对象的方法。

【问题讨论】:

  • 顺便说一句,room 的默认值应该是 {} 而不是 []
  • 好地方。固定!

标签: javascript functional-programming ramda.js


【解决方案1】:

我想我会像 Option 一样使用 List monad:

const getRoom = user => "currentRoom" in user ? [user.currentRoom()] : [];
const getMessages = room => "messages" in room ? room.messages() : [];

const allTogether = R.compose(R.chain(getMessage), R.chain(getRoom), R.of);
console.log(allTogether(Users.findOne({ username: params.id })));

【讨论】:

  • 现在空数组在代码中是不明确的:它可能意味着不确定的选择或异常。我不知道这是不是一个好建议。
  • @ftor 我从未见过用于异常的数组?空数组意味着别无选择。我同意这不是最干净的解决方案(对许多赞成票感到惊讶),也许Option<Array<Message>> 会更好;不幸的是,Ramda 没有内置选项类型。
【解决方案2】:

您可以使用仅使用 Ramda 的无点解决方案。首先,我们定义一个withDefaults 函数,它将在这些方法未定义的对象中设置currentRoommessages 方法。

var withDefaults = R.pipe(

    // if don't have `currentRom` add a
    // `currentRom` function that returns an empty object
    R.unless(
        R.hasIn('currentRoom'), 
        R.assoc('currentRoom', 
            R.always({}))), 

    // if don't have `messages` add a
    // `messages` function that returns an empty array
    R.unless(
        R.hasIn('messages'), 
        R.assoc('messages', 
            R.always([]))))

此函数根据需要过滤对象设置方法。用法示例。

var user = withDefaults(getById(id))

接下来,定义一个 getter 函数来从对象中获取房间和消息。 invoker 是这段代码的核心部分,它返回一个调用方法的函数。见http://ramdajs.com/docs/#invoker

var getCurrentRoom = R.invoker(0, 'currentRoom')
var getMessages = R.invoker(0, 'messages')

以上代码可以如下使用。

var userWithRoom = withDefaults({
        currentRoom : function () {
            return {
                number : '123'
            }
        }
    })

var userWithMessages = withDefaults({
        messages : function () {
            return [
                'get lunch'
            ]
        }
    })

var userWithAll = withDefaults({
        currentRoom : function () {
            return {
                number : '123'
            }
        },
        messages : function () {
            return [
                'get lunch'
            ]
        }
    })

var userWithNone = withDefaults({})

大家一起

var withDefaults = R.pipe(
    R.unless(
        R.hasIn('currentRoom'), 
        R.assoc('currentRoom', 
            R.always({}))), 
    R.unless(
        R.hasIn('messages'), 
        R.assoc('messages', 
            R.always([]))))

var getCurrentRoom = R.invoker(0, 'currentRoom')
var getMessages = R.invoker(0, 'messages')

// examples

var userWithRoom = withDefaults({
        currentRoom : function () {
            return {
                number : '123'
            }
        }
    })

var userWithMessages = withDefaults({
        messages : function () {
            return [
                'get lunch'
            ]
        }
    })

var userWithAll = withDefaults({
        currentRoom : function () {
            return {
                number : '123'
            }
        },
        messages : function () {
            return [
                'get lunch'
            ]
        }
    })

现在让我们使用console.log 测试上面的代码,看看我们的解决方案是否按预期工作

console.log(getCurrentRoom(userWithRoom))
console.log(getCurrentRoom(userWithMessages))    
console.log(getCurrentRoom(userWithAll))    
console.log(getCurrentRoom(userWithNone))

console.log('---')

console.log(getMessages(userWithRoom))    
console.log(getMessages(userWithMessages))    
console.log(getMessages(userWithAll))    
console.log(getMessages(userWithNone))

输出应该是:

{ number: '123' }
{}
{ number: '123' }
{}
---
[]
[ 'get lunch' ]
[ 'get lunch' ]
[]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-10-11
    • 2020-06-28
    • 2013-04-07
    • 2018-06-09
    • 1970-01-01
    • 2018-03-10
    相关资源
    最近更新 更多