接受以下内容的函数:字符串或函数或两个对象

时间:2012-11-13 07:20:52

标签: javascript node.js

我正在Node.js中创建一个模块,它只公开一个名为direct的函数,基本上是一个请求路由器(是的,我正在制作我自己的,以便学习)。但是,我想简化API只使用一个函数。其他所有内容都会被锁定,具体取决于direct - ed。

现在将接受3种类型的输入:字符串(路由)或函数(回调)或两个对象 - 来自http.createServer的请求和响应对象:

direct('/');           //pass a route string
direct(function(){});  //pass callback
direct(req,res);       //pass the request and response

这些内部因素让我担心。目前我在做:

//if only one, 
if(arguments.length === 1) {
    if( typeof arguments[0] === 'string') {
        //add to routes
    } else if( typeof arguments[0] === 'function') {
        //add to callbacks
    } else {
        //return an error
    }
} else if(arguments.length === 2 && ...check if both are typeof object, not null, not instance of array...) {
    //extremely long check if both are objects
    //planning to extract the check as a function
} else {
    //return an error object
}

如你所见,似乎我很难编写很多东西。此外,检查效率低,有点长。

  • 根据给定的标准过滤参数的有效方法是什么?
  • 有没有办法检查发送的对象是request的{​​{1}}和response个对象?

4 个答案:

答案 0 :(得分:1)

如果你这样直接实现它可能会更容易:

direct = function(o){

  if(o['route'])
    DO SOMTHING
  }

  if(o['fn']){
    DO SOMETHING ELSE
  }
  ...
}

总是会得到一个能够保持调用者意图的配置对象。

答案 1 :(得分:1)

您可以使用基于typeof的查找表:

var handlers = {
    'string':   { n: 1, fn: function(route)     { ... } },
    'function': { n: 1, fn: function(callback)  { ... } },
    'object':   { n: 2, fn: function(req, resp) { ... } }
};

然后:

var handler = handlers[typeof arguments[0]];
if(!handler) {
    // throw a hissy fit and bail out
}
if(arguments.length != handler.n) {
    // throw a different hissy fit and bail out.
}
return handler.fn.apply(null, arguments);

你也可以抛弃n并使用处理函数的length属性:

var handlers = {
    'string':   function(route)     { ... },
    'function': function(callback)  { ... },
    'object':   function(req, resp) { ... }
};

var handler = handlers[typeof arguments[0]];
if(!handler) {
    // throw a hissy fit and bail out
}
if(arguments.length != handler.length) {
    // throw a different hissy fit and bail out.
}
return handler.apply(null, arguments);

您可以进一步将handler.n检查抽象为一个函数,然后检查器的'object'版本可以使用instanceof来确保reqresp是正确的事情。这会让你的direct看起来像这样:

var handlers = {
    'string': {
        good_args: function(arguments) { ... },
        fn: function(route) { ... }
    },
    //...
};

var handler = handlers[typeof arguments[0]];
if(!handler) {
    // throw a hissy fit and bail out
}
if(!handlers.check_args(arguments)) {
    // throw a different hissy fit and bail out.
}
return handler.fn.apply(null, arguments);

如果您需要处理更多复杂性和可变性,那么您可以将handlers中的简单对象替换为支持已知接口的“真实”对象。虽然闻起来像过度工程,我可能会停留在good_args版本。

你正在构建一个微型命令解释器,不妨让它看起来像一个。

答案 2 :(得分:1)

  
      
  • 有没有办法检查发送的对象是否是http.createServer的请求和响应对象?
  •   

这部分很容易。

来自docs

  

requesthttp.ServerRequest的一个实例,responsehttp.ServerResponse的实例

所以你的代码看起来像这样,假设你的direct函数采用命名的形式参数ab(我认为arguments[0]和{arguments[1]更具可读性{1}}):

else if (arguments.length == 2
        && a instanceof http.ServerRequest
        && b instanceof http.ServerResponse)

答案 3 :(得分:0)

我想和你一样,如果你只是传递数据,那么有些功能更优雅,更容易使用。

你的代码是正确的,但你太严格了。 Javascript是一种弱类型语言。如果您开始检查每个参数的类型,您将永远不会结束,并且一行函数可能变得过于复杂。如果你在你的文档中说该函数接收2个字符串,那么用户必须传递2个字符串,如果他决定传递一个布尔值和一个函数,那不是你的问题。

我会写下以下内容:

var direct = function (param, res){
  var type = typeof param;
  if (type === "string"){
    //direct("/")
  }else if (type === "function"){
    //direct(function(){})
  }else{
    //direct(req, res)
  }
};