从documentation of the redis npm package,很明显,它采用标准的节点样式的回调。在标准的Node-style回调中,传递给您提供的回调的第一个参数是错误或null
;这就是报告错误的地方和方式。 (你甚至在你的代码中定义了一个叫err
的参数。)它们不能被try/catch
捕获,因为在错误发生很久以前,控制已经超出了try/catch
(事实上它已经不在函数中)。
所以,你会处理这样的:
module.exports = (req, res, next) => {
const redis = require('redis')
const client = redis.createClient()
client.select('2d', (err) => { // instead of 2 number, i use '2d' string, to generate an error on purpose
if (err) {
// Handle error here
err.type = 'SilentSystem'
next(err)
} else {
// Handle success here
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
client.set(ip, true, 'EX', 120, (err, rep) => {
if (err) {
err.type = 'SilentSystem'
next(err)
} else {
next()
}
})
}
})
}
在评论你说:
我实际的代码是一个比较复杂的,所以我想避免打电话,以免使用try
重复呼叫if(err)
和next(err)
。在这里处理错误有什么更好的方法(不太详细)?
不幸的是,这就是节点式回调的本质。一种选择是给自己一个过滤功能,让所有这些结果都通过,所以你的常见错误处理代码就在那里。
但是:您可能会考虑使用一个“promisifies”节点式回调函数库,以便您可以使用promise,并使用它们的链接机制来完成集中式错误处理。 (一个这样的包是promisify
,但还有其他的。)随着client.select
,client.set
“promisified”版本等,这些代码可能看起来像这样:
module.exports = (req, res, next) => {
const redis = require('redis')
const client = makeNiftyPromiseVersionOf(redis.createClient())
client.select('2d')
.then(data => {
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
return client.set(ip, true, 'EX', 120)
})
.then(() => {
next()
})
.catch(err => {
err.type = 'SilentSystem'
next(err)
})
}
注意的错误处理是如何在巩固结束;如果client.select
中有错误,则跳过then
回调,并将控制传递给catch
。如果不是,则执行then
回调并执行client.set
,并且其中的任何错误也将转到该catch
。
这也将打开大门,使用ES2017的async
/await
在同步风格编写异步代码:
module.exports = (req, res, next) => {
(async() => {
const redis = require('redis')
const client = makeNiftyPromiseVersionOf(redis.createClient())
try {
const data = await client.select('2d');
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
await client.set(ip, true, 'EX', 120)
next()
} catch (err) {
err.type = 'SilentSystem'
next(err)
}
})();
}
附注:我会删除require
呼叫出来的导出函数的 ,而是在模块级别上执行:
const redis = require('redis')
module.exports = {
// ...
}
我的实际代码有点复杂所以我试图避免调用if(err),然后使用try返回next(err)。在这里处理错误有什么更好的方法(不太详细)? –
*尝试避免重复调用,如果(err)和next(err)应该读取 –
@ S.Schenk:不幸的是,这就是节点式回调的本质。我用一个建议添加了答案的结尾。 –