Akhilesh krishnan
Akhilesh krishnan

Reputation: 799

How to have optional parameters in between mandatory parameters in JavaScript function

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

Answers (2)

talemyn
talemyn

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:

  • iterate through them using a starting index of 1 and running through them while the index was less than argLength - 2, or
  • convert the arguments object into an array and slice the values out into their own array

NOTE: I do NOT recommend this approach, but, technically, it is possible.

Upvotes: 0

HBP
HBP

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

Related Questions