1

我正在 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
}

如您所见,我似乎在对大部分内容进行硬编码。此外,检查效率低下且有点长。

  • 根据给定标准过滤参数的有效方法是什么?
  • 有没有办法检查发送的对象是否是requestresponse的对象http.createServer
4

4 回答 4

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用来确保req并且resp是正确的东西。这会让你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版本上。

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

于 2012-11-13T07:52:41.250 回答
1
  • 有没有办法检查发送的对象是否是 http.createServer 的请求和响应对象?

这部分很容易。

文档

request是一个实例http.ServerRequest并且response是一个实例http.ServerResponse

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

else if (arguments.length == 2
        && a instanceof http.ServerRequest
        && b instanceof http.ServerResponse)
于 2012-11-14T08:27:02.693 回答
1

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

direct = function(o){

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

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

总是得到一个配置对象来保存调用者的意图。

于 2012-11-13T07:28:49.753 回答
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)
  }
};
于 2012-11-13T13:04:48.223 回答