javascriptfunctiondecoratorwrappermethod-modifier

Common check for two functions which prevents calling functions from executing further


Let's say we have two functions which first do some parameter checking. They return early if the checks are not met. Then they do stuff. Quite simple:

function funcA (inputParam) {
  if(!inputParam.valueA) {
     // Do error handling
     return;
  }
  // Do stuff
}

function funcB (inputParam) {
  if(!inputParam.valueB) {
     // Do error handling
     return;
  }
  // Do stuff
}

Now, after implementing and using those functions frequently, we realize that there is another condition which needs to be met in both functions. Of course, we do not want to copy&paste that parameter check, but re-use it for both functions. It is not that simple to put it into a function and call the function because the called function would need to make sure that the rest of the caller function is not executed if the param check fails.

A function like

function checkC (inputParam) {
  if(!inputParam.valueC) {
     // Do error handling
     return;
  }
}

will not work, because if we call it like

function funcA (inputParam) {
  checkC(inputParam)
  // Do stuff
}

then it will always reach Do stuff no matter the outcome of the parameter check, but if you do

function funcA (inputParam) {
      return checkC(inputParam)
      // Do stuff
    }

then Do stuff will never be reached of course.

So, what would be the most elegant way which requires the least refactoring?

Ideas I came up with:

  1. Build a common function which would to be called first like
function commonFunction(inputParam, proceedWithAOrB) {
  if(!inputParam.valueC) {
    // Do error handling
    return;
  }
  if(proceedWithAOrB === 'a') {
    return funcA (inputParam);
  }
  if(proceedWithAOrB === 'b') {
    return funcB (inputParam);
  }
}

But that would require a significant amount of refactoring.

  1. Split up the common function into one which checks the param and one which does the error handling like
    function checkParamC (inputParam) {
      if(!inputParam.valueC) {
         return false;
      }
      return true
    }
    
    function checkParamCErrorHandling (inputParam) {
      // Do error handling
    }
    
    function funcA (inputParam) {
      if(!checkParamC (inputParam)) {
         return checkParamCErrorHandling (inputParam);
      }
      // Do stuff
    }

That way, we would not need to copy&paste actual logic, but it is still not very elegant.

I feel like that I'm missing something and there must be a more elegant solution to this?

Edit For some reason, throw new Error... is not an option in my case.


Solution

  • You could use a mixin...

    function requireCheckC(callable){
        return function(inputParam){
            if(!inputParam.valueC) {
                // Do error handling
                return;
            }
            return callable(inputParam);
        }
    }
    
    const funcA = requireCheckC(function(inputParam) {
        if(!inputParam.valueA) {
           // Do error handling
           return;
        }
        // Do stuff
    });
    

    Basically the requireCheckC will return a function that first checkC and then follow with the execution of the function passed in parameter.

    While I'd still say the best way would be to use error throwing for... well, handling errors...