多个if重构

时间:2019-02-07 12:13:22

标签: javascript functional-programming sanctuary

我具有此功能,有两个if,我要根据接收的字母数字代码查找用户。我该如何使用 sanctuary-js 重构它?

//const code = '0011223344';
const code = 'aabbc';

const isNumberCode = code => !!/^[0-9]{10}$/.exec(code);
const isLiteralCode = code => !!/^[A-Za-z]{5}$/.exec(code);

const findUser = (criteria) => {
    return new Promise(function(resolve, reject) {
      setTimeout(function() {
        resolve('user object');
      }, 300);
    });
}

async function handler(code) {
    if (isNumberCode(code)) {
       const user = await findUser({id: code});
        return user;
    }
    if (isLiteralCode(code)) {
       const user = await findUser({identifier: code});
       return user;
    }

    return 'not found';
}

async function run() {
    const user = await handler(code);

    console.log(user)
}

run();

我不明白应该如何处理三种不同的类型:数字代码文字代码找不到代码

-更新

这是我的功能解决方案(我可能会这样认为):

const Code = x => ({
  chain: f => f(x),
  fold: (e, a, f) => e(x)
});

const ErrorCode = x => ({
  fold: (e, a, f) => e(x),
  findLabel: f => ErrorCode(x)
});

const PromiseToCode = promise => ({
  fold: (e, a, f) => promise.then(x => x.fold(e, a, f))
});

const NumberCode = x => ({
  fold: (e, a, f) => a(x),
  findLabel: f => PromiseToCode(f(x, {activationCode: x}, NumberCode))
});

const LiteralCode = x => ({
  fold: (e, a, f) => f(x),
  findLabel: f => PromiseToCode(f(x, {finderCode: x}, LiteralCode))
});

const checkTypeOfCode = code => {
  if (isNumberCode(code)) {
    return NumberCode(code);
  }
  if (isLiteralCode(code)) {
    return LiteralCode(code);
  }
  return ErrorCode(code);
};

const find = async (code, criteria, type) => {
  const user = findUser();
  if (!user) {
    return ErrorCode(code);
  }
  return type(user);
};

const handler2 = (code) =>
    Code(code)
    .chain(checkTypeOfCode)
    .findLabel(find)
    .fold(
        e => 'not found',
        a => 'user object find by id',
        l => 'user object find by identifier'
    )

handler2(code).then(console.log);

但是我不知道这是否是好的代码。我也在问有关sanctuary-js的问题,因为我认为所有这些对象都不是编程的好方法。

2 个答案:

答案 0 :(得分:0)

由于您正在寻找功能更强大的重组,因此可以尝试以下操作:

将代码分成更小,更独立的部分:

  • findUser:此函数负责提供UserObjectNot found
  • 创建一个函数getCriteria,它将具有关于isNumberCodeisLiteralCode等的所有逻辑。这将返回一个条件对象或undefined
  • handler应该负责获取条件,并基于该回报findUser的响应。任何清理代码都可以保留在此处,但这是一个集线器函数,它调用各种函数并返回输出。它应该具有最低限度的业务逻辑。
//const code = '0011223344';
const code = 'aabbc';

const isNumberCode = code => !!/^[0-9]{10}$/.exec(code);
const isLiteralCode = code => !!/^[A-Za-z]{5}$/.exec(code);

const findUser = (criteria) => {
  return new Promise(function(resolve, reject) {
    if (!criteria) resolve('not found')
    setTimeout(function() {
      resolve('user object');
    }, 300);
  });
}

function getCriteria(code) {
  if (isNumberCode(code)) {
    return { id: code };
  }
  if (isLiteralCode(code)) {
    return { identifier: code }
  }
}

async function handler(code) {
  const user = await findUser(getCriteria(code))
  return user;
}

async function run() {
  const user = await handler(code);

  console.log(user)
}

run();

答案 1 :(得分:0)

您可以为多种输入类型创建枚举,并使用switch语句,如下所示。

// Enum for search-parameters
var ParameterTypes = 
{
  NUMBER :1 ,
  LITERAL:2 ,
  OTHER : 3
}

function getParameterType()
{
  //responsible to get search-parameter
  return isNumberCode(code) ? ParameterTypes.NUMBER : 
    ( isLiteralCode(code) ? ParameterTypes.LITERAL : ParameterTypes.OTHER);
}

async function handler(code) 
{
    //responsible to search user
    var user;

    switch(getParameterType())    
    {
      case ParameterTypes.NUMBER : 
          user = await findUser({id: code}); 
          //console.log('number');
          break;

      case ParameterTypes.LITERAL :           
          user = await findUser({identifier: code}); 
          //console.log('literal');
          break;

      case ParameterTypes.OTHER : 
          user = 'not found';      
          //console.log('other');    
          break;
    }   

    return user;
}