Pia*_*mso 15 javascript error-handling node.js coffeescript express
我在Node.js和Express中有应用程序.我需要为它编写测试.我在处理Express应用程序错误时遇到问题.我发现这个如何捕获node.js/express服务器错误,如EADDRINUSE?,但它对我不起作用,我不知道为什么.我想处理在执行expressApp.listen()时可能发生的错误(EADDRINUSE,EACCES等).
express = require('express')
listener = express()
#doesn't work for me
listener.on('uncaughtException', (err) ->
#do something
)
#doesn't work too
listener.on("error", (err) ->
#do something
)
#this works, but it caughts all errors in process, I want only in listener
process.on('uncaughtException', (err) ->
#do something
)
listener.listen(80) #for example 80 to get error
Run Code Online (Sandbox Code Playgroud)
有任何想法吗?
Mar*_*ica 74
这应该做的伎俩:
listener.listen(80).on('error', function(err) { });
Run Code Online (Sandbox Code Playgroud)
什么listener.listen实际上做的是创建一个HTTP服务器和调用它听:
app.listen = function(){
var server = http.createServer(this);
return server.listen.apply(server, arguments);
};
Run Code Online (Sandbox Code Playgroud)
Rob*_*sch 22
首先,expressJS不抛出uncaughtException事件,进程确实如此,所以你的代码不起作用也就不足为奇了.
所以使用:process.on('uncaughtException',handler)代替.
接下来,expressJS已经提供了一种标准的错误处理方法,即使用它为此目的提供的中间件功能,如:
app.configure(function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
Run Code Online (Sandbox Code Playgroud)
此函数向客户端返回一条错误消息,带有可选的堆栈跟踪,并在connectJS errorHandler中记录.
(请注意,errorHandler实际上是connectJS的一部分,仅由expressJS公开.)
如果现有errorHandler提供的行为不足以满足您的需求,则其源代码位于connectJS的errorHandler中间件,可以轻松修改以满足您的需求.
当然,不是直接修改这个函数,"正确"的方法是创建自己的errorHandler,使用connectJS版本作为起点,如:
var myErrorHandler = function(err, req, res, next){
...
// note, using the typical middleware pattern, we'd call next() here, but
// since this handler is a "provider", i.e. it terminates the request, we
// do not.
};
Run Code Online (Sandbox Code Playgroud)
并将其安装到expressJS中:
app.configure(function(){
app.use(myErrorHandler);
});
Run Code Online (Sandbox Code Playgroud)
请参阅Just Connect it,已经有关于connectJS的想法filter和provider中间件的解释以及如何为Connect/Express编写中间件,以获得精心编写的教程.
这些对你也可能有用:
最后,关于测试expressJS的一个很好的信息来源可以在它自己的测试中找到.
提及:Marius Tibeica 的回答是完整而伟大的,还有david_p评论。Rob Raisch 的回答也是如此(探索有趣)。
/sf/answers/1892831601/
/sf/answers/932873861/
第一种方法很糟糕!我留下它作为参考!请参阅更新部分!对于好版本!以及原因的解释!
对于那些会发现这很有用的人,这里有一个实现繁忙端口处理的功能(如果端口繁忙,它将尝试使用下一个端口,直到找到一个不繁忙的端口)
app.portNumber = 4000;
function listen(port) {
app.portNumber = port;
app.listen(port, () => {
console.log("server is running on port :" + app.portNumber);
}).on('error', function (err) {
if(err.errno === 'EADDRINUSE') {
console.log(`----- Port ${port} is busy, trying with port ${port + 1} -----`);
listen(port + 1)
} else {
console.log(err);
}
});
}
listen(app.portNumber);
Run Code Online (Sandbox Code Playgroud)
函数 listen 递归调用自身。在端口繁忙错误的情况下。每次增加端口号。
首先,这个版本是遵循与 nodejshttp.Server.listen()方法相同的签名的版本!
app.portNumber = 4000;
function listen(port) {
app.portNumber = port;
app.listen(port, () => {
console.log("server is running on port :" + app.portNumber);
}).on('error', function (err) {
if(err.errno === 'EADDRINUSE') {
console.log(`----- Port ${port} is busy, trying with port ${port + 1} -----`);
listen(port + 1)
} else {
console.log(err);
}
});
}
listen(app.portNumber);
Run Code Online (Sandbox Code Playgroud)
听(serverOrExpressApp,[端口[,主机[,积压]]][,回调])
就像按照
https://nodejs.org/api/net.html#net_server_listen_port_host_backlog_callback
回调签名改为
(端口)=> 无效
function listen(server) {
const args = Array.from(arguments);
// __________________________________ overriding the callback method (closure to pass port)
const lastArgIndex = arguments.length - 1;
let port = args[1];
if (typeof args[lastArgIndex] === 'function') {
const callback = args[lastArgIndex];
args[lastArgIndex] = function () {
callback(port);
}
}
const serverInstance = server.listen.apply(server, args.slice(1))
.on('error', function (err) {
if(err.errno === 'EADDRINUSE') {
console.log(`----- Port ${port} is busy, trying with port ${port + 1} -----`);
port += 1;
serverInstance.listen.apply(serverInstance, [port].concat(args.slice(2, lastArgIndex)));
} else {
console.log(err);
}
});
return serverInstance;
}
Run Code Online (Sandbox Code Playgroud)
与旧示例相反!这个方法不会调用自己!
关键要素:
重要的
const server = listen(app, 3000, (port) => {
console.log("server is running on port :" + port);
});
// _____________ another example port and host
const server = listen(app, 3000, 'localhost', (port) => {
console.log("server is running on port :" + port);
});
Run Code Online (Sandbox Code Playgroud)
为什么我们在这里跳过回调!?
回调一次添加!它在服务器实例内部保存在一个数组中!如果我们再加一个!我们将有多个触发器!关于(尝试次数 + 1)的次数。所以我们只在第一次尝试中包含它!
这样我们就可以直接返回服务器实例了!并继续使用它来尝试!而且做得很干净!
这也有助于一目了然地更好地理解
serverInstance.listen.apply(serverInstance, [port].concat(args.slice(2, lastArgIndex)));
Run Code Online (Sandbox Code Playgroud)
这里的参数端口变量播放就关闭了!
function listen(server, ...args) {
// __________________________________ overriding the callback method (closure to pass port)
const lastArgIndex = args.length - 1;
let port = args[0];
if (typeof args[lastArgIndex] === 'function') {
const callback = args[lastArgIndex];
args[lastArgIndex] = function () {
callback(port);
}
}
const serverInstance = server.listen(server, ...args)
.on('error', function (err) {
if(err.errno === 'EADDRINUSE') {
console.log(`----- Port ${port} is busy, trying with port ${port + 1} -----`);
port += 1;
serverInstance.listen(...[port, ...args.slice(1, lastArgIndex)])
} else {
console.log(err);
}
});
return serverInstance;
}
Run Code Online (Sandbox Code Playgroud)
说得对,真的不是!但是第一个版本!我们在每次失败时调用函数本身!每次它都会创建一个新实例!垃圾收集器会动一些肌肉!
没关系,因为这个函数只在开始时执行一次!
旧版本没有返回服务器实例!
你可以看@sakib11评论,看看他陷入了什么问题!可以考虑周到!
同样在评论中,我提到了 promise 版本和闭包 getter 模式!我不认为他们有趣!上面的方式只是尊重与nodejs相同的签名!也回调就好了!我们正在将我们的服务器参考写掉!有承诺版本!一个承诺得到返回,并在决议我们传递所有元素!服务器实例+端口!
如果你想知道闭包吸气模式!(这里不好)
在我们的方法中,我们创建了一个引用服务器实例的 ref!如果我们不能像我们所做的那样返回服务器实例(想象它是不可能的!所以每次创建一个新实例!模式包括创建一个闭包(该范围内的方法)并返回它!
所以为了使用
function listen(server, port, callback) {
const serverInstance = server.listen(port, () => { callback(port) })
.on('error', function (err) {
if(err.errno === 'EADDRINUSE') {
console.log(`----- Port ${port} is busy, trying with port ${port + 1} -----`);
port += 1;
serverInstance.listen(port);
} else {
console.log(err);
}
});
return serverInstance;
}
Run Code Online (Sandbox Code Playgroud)
但这只是开销,特别是我们需要等待服务器完成!除非我们设置它使用回调的方式!或返回一个承诺!
它只是过于复杂了!而且一点都不好!
只是因为我提到了!
上面的方法可以调整!添加尝试次数限制!并添加一些事件或钩子!但是很好!一般我们只需要一个简单的函数就可以尝试并实现它!对我来说,以上就足够了!
从文档
app.listen() 方法返回一个 http.Server 对象,并且(对于 HTTP)是以下内容的便捷方法:
function listen(server, ...args) {
// __________________________________ overriding the callback method (closure to pass port)
const lastArgIndex = args.length - 1;
let port = args[0];
if (typeof args[lastArgIndex] === 'function') {
const callback = args[lastArgIndex];
args[lastArgIndex] = function () {
callback(port);
}
}
const serverInstance = server.listen(server, ...args)
.on('error', function (err) {
if(err.errno === 'EADDRINUSE') {
console.log(`----- Port ${port} is busy, trying with port ${port + 1} -----`);
port += 1;
serverInstance.listen(...[port, ...args.slice(1, lastArgIndex)])
} else {
console.log(err);
}
});
return serverInstance;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
16766 次 |
| 最近记录: |