Reputation: 71
I have been using functions as parameters. Now I need to pass a function A which requires parameters x generated by function B. I can do that too. by calling A in B with the parameters.
But my problem is, my function B accepts any kind of function, and it is not fixed. It may take function C also which requires parameter y or some function D that does not need any parameter.
Is this possible?
function B(done_function){
//some task generate some value
done_function();
}
function B(done_function){
//some task generate some value including args
done_function(args);
}
How can I make A, C and D functions execute with their arguments.
The top two examples won't work.
Upvotes: 1
Views: 44
Reputation: 350147
Let B call the callback with a single object as argument, which contains all information:
function B(done_function){
//some task generating some values, including args, for example:
var args = {
status: 3,
code: 'DEC',
location: 'Atlantic',
date: new Date('2017-01-01')
}
done_function(args);
}
Using ES6 destructuring in function parameters, you can filter out the information you need:
Function A could look like this:
function A({status}) {
console.log('status is ' + status);
}
B(A);
In the same way, C could look like this:
function C({code, date}) {
console.log('code is ' + code + ' on ' + date);
}
B(C);
Of course, ES6 destructuring is just a nice shortcut syntax, as you can do it also like this:
function A(response) {
console.log('status is ' + response.status);
}
B(A);
length
propertyIf the distinction between different kinds of callbacks can be made on the basis of the number of parameters that are defined for them, then you could use the length
property like this:
function B(done) {
var code = 'DEC';
var status = 1;
var location = 'Atlantic';
var date = new Date('2017-01-01');
switch (done.length) {
case 1:
done(status);
break;
case 2:
done(location, date);
break;
default:
done(code, status, location, date);
}
}
function A(status) {
console.log('status = ' + status);
}
function C(location, date) {
console.log('location = ' + location + ' on ' + date.toDateString());
}
B(A);
B(C);
Note the specific rules that apply for the length
property's value.
Upvotes: 0
Reputation: 113866
The normal way to handle this is to ignore it. Function B
should simply not care about how other functions accept arguments. Instead it should only provide a standard and well documented interface to it's callback:
function B (done_function) {
// do some stuff to generate result
done_function(result);
}
Or if function B
can possibly generate errors asynchronously then it should do done_function(err, result)
. Notice that all libraries do this. They don't care how you write your functions.
Now, how to pass various types of functions to B
? Just wrap them around another function. For example, say you need to pass the result of B
to a logger function and you need to pass a variable specifying the name of the file to log to. Just do this:
B(function(result) {
logToFile(debugLogFile, result);
});
Say for example you need to modify the result because the function you want to pass it to expect it to be in a specific format. Just do something like this:
B(function(result) {
var x = {
some_parameter: something,
result: result
};
doSomethingElse(x);
});
There is no scenario where function B
needs to be aware of how you want to process the result it generates. It's you, the programmer, who is responsible to convert the result of function B
appropriately before doing further processing.
Upvotes: 1
Reputation: 3183
You can make use of the functions call method:
function B(done_function){
//some task generate some value including args
done_function.call(done_function, args);
}
Upvotes: 0