1

I have a working but tedious code.

I have 6 of the onoff objects to describe 6 GPIO inputs. All of them need to register a callback [i.e. obj.watch(callback)] to detect state change.

Currently, my functional code looks like this

Var states = [[0,0], [0,0], [0,0]];
Var handle0 = function (err, A) {
    State[0][0] = A;
    Eval0(state[0]);
}
Var handle1 = function (err, A) {
    State[0][1] = A;
    Eval0(state[0]);
}
Var handle2 = function (err, A) {
    State[1][0] = A;
    Eval1(state[1]);
}
Var handle3 = function (err, A) {
    State[1][1] = A;
    Eval1(state[1]);
}
Var handle4 = function (err, A) {
    State[2][0] = A;
    Eval2(state[2]);
}
Var handle5 = function (err, A) {
    State[2][1] = A;
    Eval2(state[2]);
}
Input0.watch(handle0);
Input1.watch(handle1);
Input2.watch(handle2);
Input3.watch(handle3);
Input4.watch(handle4);
Input5.watch(handle5);

As you can see, the routines are mostly the same, but just need to access different variables. However, since the onoff.watch callback expect a function to handle two parameters (error status, and value), I don’t know how to extend my callback to make it generic to include my state information.

Are there a design pattern to simplify these callback creation?

Patrick
  • 4,186
  • 9
  • 32
  • 45

1 Answers1

1

The term you're looking for is partial application. Make a general handle function as so:

function handle(x, y, evalFn, err, A) {
    State[x][y] = A;
    evalFn(state[x]);
}

What you would like is a higher-order function that takes a function, fixed values for the some of the arguments, and returns a new function taking "the rest of the arguments" that calls the original function with the fixed arguments and the given arguments.

Such a technique is called partial application. You could write this function yourself as (using standard ES6 syntax available in modern versions of Node):

function partial(fn, ...fixedArgs) {
    return (...args) => fn(...fixedArgs, ...args)
}

This is also available in Lodash as it is a very common design pattern.

Then you can assign handlers as

Input0.watch(partial(handle, 0, 1, Eval0));

Because partial(handle, 0, 1, Eval0) is itself a function whose first two arguments will become err and A in the handler.

cemulate
  • 2,305
  • 1
  • 34
  • 48