简体   繁体   English

如何在JavaScript中使用回调处理可选参数

[英]How to handle optional parameters with callback in javascript

//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. 这里sendMessage()函数已经编写,并且在没有FormData参数的所有模块中都可以很好地使用( sendMessage(type,url,method,json,retries,cb) ),但是对于文件上载,我们需要使用formData传递文件路径而无需全部更改其他功能是可能的。

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: 并且,始终需要使用callback参数,然后,您可以像这样进行操作:

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? 如何重载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. 然后,原始函数将变成一个外壳程序,该外壳程序将使用新参数null调用新函数。

 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. 尽管此方法有效且不使用重载,但它只是一次拍摄,因为您不想以sendMesage3,sendMessage4等结尾。...sendMessage2可能应该使用可扩展性更高的options对象,因此您不会再被迫这样做。 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. 然后,稍后在您具有更大的灵活性时,可以将较旧的代码切换到options对象,并完全摆脱整个两个API方案。

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. 请注意,我将回调保留在options对象之外,因为这使该函数与典型的异步调用约定兼容,并为调用者提供了内联回调,以使调用者可以编写代码。

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. 尝试并从原始方法中提取尽可能多的功能以保持代码DRY。

If possible, write a test that both original and new methods can pass. 如果可能,编写一个测试,使原始方法和新方法都可以通过。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM