我一直试图(基本上)创建一个工厂函数,为我所拥有的十几个较小的专用服务器配置和构建一个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);
这两个示例都是工厂上下文的一部分,我故意减少传递给函数的参数。
任何帮助都将不胜感激。
答案 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
,以便您与核心库保持同步。我一直使用节点模块这样做。
这样做有两个好处:
您可以完全控制自定义您认为合适的代码,同时了解原始作者编写的代码。
如果您发现了错误或构建了一个很酷的功能,您可以提交拉取请求以使整个社区受益。
您首先要对存储库进行分叉,然后获取您的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
希望这有帮助。