如何在 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;
}
这里的 sendMessage() 函数已经写好了,并且在没有 FormData 参数的所有模块中使用得很好(sendMessage(type,url,method,json,retries,cb)
),但是对于文件上传,我们需要使用 formData 传递文件路径而不改变所有其他函数是有可能。
如果你要支持的两种不同的调用方案是这样的:
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);
}
虽然这有效并且不使用重载,但它有点像 one-time 镜头,因为您不想以 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});
}
请注意,我将回调排除在选项对象之外,因为这使得该函数与典型的异步调用约定兼容,并为调用者清洁程序编写内联回调。
创建一个接受对象作为参数的新方法,该方法分析对象并决定是代理到原始函数还是执行您的新要求。
将原始方法标记为已弃用并记录以使用您的新方法,在适当的时候,可以替换对原始方法的调用。当它们全部被替换后,重构你的新函数以删除代理,并在有把握时删除旧方法。
尝试从原始方法中抽象出尽可能多的有意义的功能,以保持代码干爽。
如果可以的话,写一个新方法和原方法都能通过的测试。
//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 传递文件路径而不改变所有其他函数是有可能。
如果你要支持的两种不同的调用方案是这样的:
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);
}
虽然这有效并且不使用重载,但它有点像 one-time 镜头,因为您不想以 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});
}
请注意,我将回调排除在选项对象之外,因为这使得该函数与典型的异步调用约定兼容,并为调用者清洁程序编写内联回调。
创建一个接受对象作为参数的新方法,该方法分析对象并决定是代理到原始函数还是执行您的新要求。
将原始方法标记为已弃用并记录以使用您的新方法,在适当的时候,可以替换对原始方法的调用。当它们全部被替换后,重构你的新函数以删除代理,并在有把握时删除旧方法。
尝试从原始方法中抽象出尽可能多的有意义的功能,以保持代码干爽。
如果可以的话,写一个新方法和原方法都能通过的测试。