仅当对象存在使用Ramda时才调用对象上的嵌套方法

时间:2016-11-29 16:09:20

标签: javascript functional-programming ramda.js

我目前有一个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类似,但对于对象上的方法。

2 个答案:

答案 0 :(得分:5)

我想我会像Option一样使用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 }))); monad:

def float_check(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

l = ['1', '2', '2.1', 'ab1', '1ab']
print([i for i in l if float_check(i)])

答案 1 :(得分:0)

您可以使用仅使用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是此snipet的核心部分,它返回一个调用方法的函数。见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' ]
[]