仅当对象存在时使用 Ramda 调用对象的嵌套方法
Call nested methods on object only if it exists using Ramda
我目前有一个 user
对象,其中有一个 currentRoom()
方法,有时可能不存在或 return null
.
如果 currentRoom()
方法 return 是什么东西,那么我需要对其调用 messages()
方法。如果两者都没有 returned,我想 return 一个默认的空数组 []
。
我想使用 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
,但是对象的方法。
我想我会像 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 })));
您可以使用仅使用 Ramda 的无点解决方案。首先,我们定义一个 withDefaults
函数,它将在未定义这些方法的对象中设置 currentRoom
和 messages
方法。
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
是这个片段的核心部分,它 returns 一个调用方法的函数。参见 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' ]
[]
我目前有一个 user
对象,其中有一个 currentRoom()
方法,有时可能不存在或 return null
.
如果 currentRoom()
方法 return 是什么东西,那么我需要对其调用 messages()
方法。如果两者都没有 returned,我想 return 一个默认的空数组 []
。
我想使用 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
,但是对象的方法。
我想我会像 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 })));
您可以使用仅使用 Ramda 的无点解决方案。首先,我们定义一个 withDefaults
函数,它将在未定义这些方法的对象中设置 currentRoom
和 messages
方法。
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
是这个片段的核心部分,它 returns 一个调用方法的函数。参见 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' ]
[]