0
//request is a node module   
var request = require('request');
 /**
     * send REST web service message to server
     * @function sendMessage
     * @param {string} method - GET, POST, PUT, DELETE
     * @param {string} url - server URL
     * @param {object} json - The data to be send
     * @param {object} cb - callback function
     *@param{object}formData-The data related to file upload
     * @returns void
     */
    function sendMessage(type,url,method,json,retries,formData,cb){
        var options={
        url:url,
        formData:formData,
        json:true,
switch (method) {
    case 'get':
      request.get(options, cb);
      break;
    case 'post':
      envelope.token = json.token;
      envelope.package = json.package;
      options.body = envelope;
      request.post(options, cb);
      break;
    case 'put':
      envelope.package = json.package;
      envelope.token = json.token;
      options.body = envelope;
      request.put(options, cb);
      break;
    case 'delete':
      request.delete(options, cb);
      break;       
 }

Here sendMessage() fuction already written and well used in all the modules without FormData parameter(sendMessage(type,url,method,json,retries,cb)),but for file upload we need to pass the file path using formData without alter all the other functions is that possible.

  • 1
    With that much parameters, I think you should use a single object instead. – Lewis Jan 26 '17 at 08:36
  • Yes, You are correct but,It is already built that way and used all over the other modules. Change is impossible right now. and I need solution without affecting other modules – Nithila Shanmugananthan Jan 26 '17 at 08:39
  • You may want to read this [How to overload functions in Javascript](http://stackoverflow.com/questions/10855908/how-to-overload-functions-in-javascript/10855939#10855939) which also covers optional arguments. – jfriend00 Jan 26 '17 at 08:44
  • Why does the formData argument need to precede the cb argument in the function definition? – AndFisher Jan 27 '17 at 10:53

2 Answers2

2

If the two different calling schemes you want to support are this:

sendMessage(type,url,method,json,retries,formData,cb)

and this:

sendMessage(type,url,method,json,retries,cb)

And, the callback argument is always required, then, you can do that like this:

function sendMessage(type,url,method,json,retries,formDataArg,cbArg) {
    var cb = cbArg, formData = formDataArg;
    // if we don't have a cb arg, then it must have been called with the
    // shorter form that doesn't have formData
    if (!cb) {
       cb = formDataArg;
       formData = null;
    }

    // continue rest of function using cb and formData as the symbols
    // for the last two arguments

    // ... other code here ...

}

As others have said, when you get this many arguments, it's often better to use a single options object to which you attach properties. Then it becomes a lot easier to make some of the arguments optional.

You may also find this useful:

How to overload functions in javascript?


FYI, there is also the way you might solve something like this in a harder typed language. You'd create a second function that takes the extra argument and move the implementation there. Then, the original function just becomes a shell that calls the new function with null for the new argument.

 function sendMessage2(type,url,method,json,retries,formDataArg,cbArg) {
      // full implementation here with all arguments, formDataArg may be null
 }

 // original function here, calling signature unchanged
 function sendMessage(type,url,method,json,retries,cbArg) {
     // call new implementation with arguments in the right place
     return sendMessage2(type, url, method, json, retries, null, cbArg);
 }

While this works and doesn't use overloading, it's kind of a one-time shot because you don't want to end up with sendMesage3, sendMessage4, etc... Probably sendMessage2 should use the options object which is a lot more extensible so you aren't forced into this again. Then, sometime later when you have more flexibility, you can switch the older code over to the options object and get rid of the whole two API scheme entirely.

That could look like this:

function sendMessageOptions(options, cb) {
     // main code here that supports formData to send the message
     // gets arguments from the options object
}

 // original function here, calling signature unchanged
 function sendMessage(type,url,method,json,retries,cbArg) {
     // call new implementation with arguments in the right place
     return sendMessageOptions({type: type, url: url: method: method, json: json: retries: retries});
 }

Note, I left the callback out of the options object because this makes the function compatible with the typical async calling convention and makes inline callbacks for the caller cleaner to code.

Community
  • 1
  • 1
jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • This could work, but has the possibility of becoming a maintenance nightmare! – AndFisher Jan 26 '17 at 09:20
  • @AndFisher - It's not a maintenance nightmare if you don't keep adding more optional arguments. As the answer already says, the right way to do this is to switch to an options object, but the OP already said that wasn't a possibility because they can't change all the other callers at this time. So, there is no other choice given that constraint. Do you know of any other way to answer the question given the constraints proposed? – jfriend00 Jan 26 '17 at 14:40
  • It will go against the concept of the doc comments, which could confuse a new developer that might inherit, but not be familiar with the project, hence maintenance problem. – AndFisher Jan 27 '17 at 10:53
  • @NithilaShanmugananthan - I added a few more options to my answer. – jfriend00 Jan 27 '17 at 17:36
  • @AndFisher - I added two other options to my answer that don't use argument overloading though I don't necessarily share your opinion that it's an evil thing, but people have opinions so there are different solutions to choose from depending upon what you like. – jfriend00 Jan 27 '17 at 17:41
1

Create a new method that accepts an object as a parameter, which analyses the object and decides whether to proxy to the original function or perform your new requirement.

Mark the original method as deprecated and document to use your new method, and when the time is right, calls to the original method can be replaced. When they are all replaced, refactor your new function to remove the proxy and, when confident, remove the old method.

Try and abstract as much functionality as makes sense from the original method to keep the code DRY.

If possible, write a test that both original and new methods can pass.

AndFisher
  • 633
  • 1
  • 5
  • 18