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

时间:2017-01-26 08:32:31

标签: javascript node.js node-webkit

//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;       
 }

这里sendMessage()函数已经编写好并且在没有FormData参数(sendMessage(type,url,method,json,retries,cb))的所有模块中使用得很好,但是对于文件上传,我们需要使用formData传递文件路径而不改变所有其他函数是可能的

2 个答案:

答案 0 :(得分:2)

如果您想支持的两种不同的呼叫方案是:

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

和此:

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

并且,总是需要回调参数,然后,你可以这样做:

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 ...

}

正如其他人所说,当你得到这么多论点时,通常最好使用附加属性的单个选项对象。然后,使一些参数可选变得容易得多。

您可能还会发现这很有用:

How to overload functions in javascript?

仅供参考,还有一种方法可以用更难的类型语言解决这类问题。你将创建第二个函数,它接受额外的参数并在那里移动实现。然后,原始函数变成一个shell,用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);
 }

虽然这有效并且不使用重载,但它是一次性镜头,因为你不想以sendMesage3,sendMessage4等结束......可能sendMessage2应该使用很多的选项对象更具可扩展性,因此您不会再被强行插入。然后,稍后当你有更多灵活性时,你可以将旧代码切换到选项对象并完全摆脱整个两个API方案。

这可能是这样的:

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});
 }

注意,我将回调从选项对象中移除,因为这使得该函数与典型的异步调用约定兼容,并使调用者清理器的内联回调编码。

答案 1 :(得分:1)

创建一个接受对象作为参数的新方法,该方法分析对象并决定是代理原始函数还是执行新要求。

将原始方法标记为已弃用,并将文档标记为使用新方法,当时间正确时,可以替换对原始方法的调用。当它们全部被替换时,重构您的新函数以删除代理,并在有信心时删除旧方法。

尝试并从原始方法中抽象尽可能多的功能,以保持代码DRY。

如果可能的话,写一个原始方法和新方法都可以通过的测试。