2016-11-29 44 views
1

我目前有一个user对象,其上有一个currentRoom()方法,有时可能不存在或返回null只有在存在使用Ramda的对象上调用嵌套方法

如果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,但主要对象的方法。

+0

顺便说一句,'room'的默认值应该是是'{}'而不是'[]' – Bergi

+0

好点。固定! – gosseti

回答

5

我想我会用List单子像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 }))); 
+0

现在,空数组在代码中不明确:它可能意味着非确定性选择或异常。我不知道这是否是一个好建议。 – ftor

+0

@ftor我从来没有见过用于异常的数组?空阵列意味着没有选择。我确实认为这不是最干净的解决方案(很多人赞同),也许'Option >'会更好;不幸的是,拉姆达没有提供内置的选项类型。 – Bergi

+0

哈哈。我喜欢。无耻的不合理的投票。 –

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' ] 
[] 
相关问题