Reputation: 799
How to create a utility function in JavaScript like below, where URL is the first parameter and success and error callbacks will be last parameters(mandatory) with any number of optional parameters in-between
function performAction(URL, optional1, optional2, successCallback, errorCallback){
//api call with given url and other parameters with callback
}
and the function should be called like below without destructuring
performAction(url, op1, success, error);
Upvotes: 2
Views: 1051
Reputation: 7950
There's really two ways to do what you are describing, but neither of them 100% meets your requirements . . .
1) Use a required options
array or object to hold optional parameters
In this approach, you would have a parameter "on call" to hold 0 or more parameters in addition to the required ones:
function performAction(URL, options, successCallback, errorCallback) {...}
This would support your desired functionality, but would force the user to provide, at a minimum, an empty Array
or Object
as the second parameter:
performAction(someURL, [], function1, function2);
performAction(someURL, [foo, bar], function1, function2);
performAction(someURL, {}, function1, function2);
performAction(someURL, {foo: "abc", bar: "xyz"}, function1, function2);
2) Use the newer "rest parameters" provided by ES6
This approach would allow you to make any additional parameters truly optional (no empty value needed), however, rest parameters are required to be the last parameter in the function:
function performAction(URL, successCallback, errorCallback, ...options) {...}
So, while you would not get the order of parameters that want, it would meet your desire to have the optional parameters be truly optional:
performAction(someURL, function1, function2);
performAction(someURL, function1, function2, foo);
performAction(someURL, function1, function2, foo, bar, baz);
Any additional parameters will be pulled together and stored in an array, that can be accessed within the function. See more on rest parameters here on MDN.
The other drawback to this approach is that ES6 is still being rolled out into browsers, so it is not supported in browsers just yet. You can use a transpiler like Babel to make it understandable to those browsers, but that does add some complexity to this approach.
UPDATE: Technically, there is also a 3rd option to work with the arguments
object that is built into JavaScript functions (more info here on MDN), but this would be messy. You would need to define the function with the three required parameters:
function performAction(URL, successCallback, errorCallback) {...}
. . . but then call the function with (potentially) more than the three expected arguments:
performAction(someURL, function1, function2);
performAction(someURL, foo, function1, function2);
performAction(someURL, foo, bar, baz, function1, function2);
The function would then need to access the parameters in a complicated way . . . you'd actually need to redefine the last two parameter values, based on their placement in the arguments
object:
var argLength = arguments.length;
successCallback = arguments[argLength - 2];
errorCallback= arguments[argLength - 1];
To access any of the remaining values, you would either need to:
argLength - 2
, orarguments
object into an array and slice
the values out into their own arrayNOTE: I do NOT recommend this approach, but, technically, it is possible.
Upvotes: 0
Reputation: 16033
Use rest parameters as follows :
function varArgs (URL, ...options) {
// Check that options has at least two values for the callbacks
if (options.length < 2)
throw (new Error ('varArgs : no callbacks specified'));
// Extract last two values in options and assign to callbacks
let cb_error = options.pop (),
cb_success = options.pop ();
// Verify that callbacks are indeed functions
if (typeof cb_error != 'function' || typeof cb_success != 'function')
throw (new Error ('varArgs : callbacks not functions!!'));
// now process URL using options and call appropriate callback.
// ....
}
Upvotes: 1