如何在expressjs中重载app.listen的功能

时间:2014-09-02 02:59:37

标签: node.js express

我一直试图(基本上)创建一个工厂函数,为我所拥有的十几个较小的专用服务器配置和构建一个expressjs服务器。部分原因是我想增加listen功能。

我想知道解决这个问题的最佳方法。我也在这里寻找可重复使用的设计选择。

正常创建服务器:

var httpServer = express();
    ...

由于express的设计方式(不确定我是否正确)我无法访问{whatever} .prototype.listen。所以我提出了两种方法。

在当前范围内使用其他变量:

 var oldListen = httpServer.listen;
 httpServer.listen = function(callback){
    ...
    oldListen.call(httpServer, options.port, options.host, function(){
       ...
       if ( typeof callback == 'function' ) callback();                    
    });
 };

哪个有效并且相当直接但是我有一个可变的吊装疣。我也有一个闭包解决方案,但我认为实际上可能过于迟钝了:

httpServer.listen = (function(superListen){
   return function(callback){
      ...
      superListen.call(httpServer, options.port, options.host, function(){
         ...               
         if ( typeof callback == 'function' ) callback();
      });
   };                                             
})(httpServer.listen);

这两个示例都是工厂上下文的一部分,我故意减少传递给函数的参数。

任何帮助都将不胜感激。

4 个答案:

答案 0 :(得分:2)

如果您坚持“重载”,请确保实现原始占用空间(这是重载的性质)。 Express listen只是节点internal http listen method的别名:

server.listen(port, [host], [backlog], [callback]);

更新: Express甚至建议使用节点的服务器API进行自定义实施:http://expressjs.com/4x/api.html#app.listen

否则,您应该创建自己的自定义listen方法,其定义如下:

httpServer.myCustomListen = function (callback) {
    httpServer.listen.call(httpServer, options.port, options.host, callback);
}

第二个选项是您最好的选择,但为了使其起作用,您必须扩展快速库。 Express是开源的,托管在Github上。把它分叉并随意修改。在新的更新中定期pull,以便您与核心库保持同步。我一直使用节点模块这样做。

这样做有两个好处:

  1. 您可以完全控制自定义您认为合适的代码,同时了解原始作者编写的代码。

  2. 如果您发现了错误或构建了一个很酷的功能,您可以提交拉取请求以使整个社区受益。

  3. 您首先要对存储库进行分叉,然后获取您的fork 的URL,克隆它,然后添加对原始“上游”存储库的引用:

    git clone [url_to your_fork]
    cd express
    git remote add upstream git@github.com:strongloop/express.git
    

    然后您可以将更改推送到您自己的仓库(git push)。如果您想从原始仓库获取更新,您可以从上游仓库提取:git pull upstream master

    如果您想将自定义快递分支添加为项目的npm模块,您可以使用以下内容:

    npm install git://github.com/[your_user_name]/express.git --save
    

答案 1 :(得分:2)

正如维克多的回答所指出的,快递的原型在express/lib/application.js。该文件用于构建表达式,并通过express/lib/express.js中的application命名空间导出。因此,可以使用.listen引用express.appliction.listen函数。

然后可以使用这种方法:(类似于Victor的方法)

var express = require('express');

express.application._listen = express.application.listen;
express.application.listen = function(callback) {
  return this._listen(options.port, options.host, callback);
};

如果您不想自己将基本函数存储在变量中,也可以使用Lo-dash的_.wrap函数。它看起来像这样:

var express = require('express');
var _ = require('lodash');

express.application.listen = _.wrap(express.application.listen, function(listenFn) {
  return listenFn(options.port, options.host, callback); // Called with the same this
};

但是,使用这些方法会遇到问题中提到的问题(变量提升,创建额外变量)。为了解决这个问题,我通常会创建自己的express.application子类并替换该子类中的.listen函数,并告诉express使用该子类。但是,由于express的当前结构,您无法在不覆盖express.application函数本身的情况下将express()替换为您自己的子类。

因此,我要做的是完全接管express.application.listen,因为它只有2行。这很简单!

var express = require('express');
var http = require('http');

express.application.listen = function(callback) {
  return http.createServer(this).listen(options.port, options.host, callback);
};

您甚至可以制作https选项!

var express = require('express');
var http = require('http');
var https = require('https');

express.application.listen = function(callback) {
  return (options.https ? http.createServer(this) : https.createServer({ ... }, this))
          .listen(options.port, options.host, callback);
};

注意:其中一个答案提到分叉表达和修改它。对于这么小的功能,我会很难证明这一点。

答案 2 :(得分:1)

您应该可以轻松地重载快速侦听功能。您可以使用以下对象路径访问它:express.application.listen

所以,你可以实现这样的东西:

var express = require('express');

express.application.baseListen = express.application.listen;
express.application.listen = function(port) {
console.log('Port is: ' + port);
  this.baseListen(port);
};

listen函数的实现位于express模块​​文件夹下的以下路径中:node_modules\express\lib\application.js

答案 3 :(得分:-1)

绑定并侦听给定主机和端口上的连接。此方法与节点的http.Server#listen()。

相同
var express = require('express');
var app = express();
app.listen(3000);

express()返回的app实际上是一个JavaScript函数,旨在作为回调处理请求传递给节点的HTTP服务器。这使您可以轻松地为应用程序的HTTP和HTTPS版本提供相同的代码库,因为应用程序不会从这些版本继承(它只是一个回调):

var express = require('express');
var https = require('https');
var http = require('http');
var app = express();

http.createServer(app).listen(80);
https.createServer(options, app).listen(443);

app.listen()方法是以下的便捷方法(如果您希望使用HTTPS或同时提供这两种方法,请使用上述技术):

app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};

<强>参考http://expressjs.com/api.html

希望这有帮助。