gpt4 book ai didi

javascript - 在异步回调中捕获尝试错误

转载 作者:行者123 更新时间:2023-11-29 19:02:17 25 4
gpt4 key购买 nike

我正在使用回调在 redis 数据库异步上设置一些 ip。

我正在 try catch 错误并通过 express 将其发送到我的错误处理程序中间件。

我故意在 select 方法上生成错误,但它没有捕获我的错误。

见以下代码:

module.exports = (req, res, next) => {
const redis = require('redis')
const client = redis.createClient()
try {
client.select('2d', (err) => { // instead of 2 number, i use '2d' string, to generate an error on purpose
const ip = req.headers['x-forwarded-for'] || req.connection.remoteAddress
client.set(ip, true, 'EX', 120, (err, rep) => {
return next()
})
})
} catch (err) {
err.type = 'SilentSystem'
next(err)
}
}

最佳答案

来自documentation of the redis npm package ,很明显它使用标准的节点式回调。在标准的 Node 风格回调中,传递给您提供的回调的第一个参数是错误或 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()
}
})
}
})
}

在您的评论中:

My actual code is a bit more complex so I was trying to avoid calling to avoid repeating calling if(err) and next(err) by using try. What's a better way (less verbose) to handle errors here?

不幸的是,这就是 Node 风格回调的本质。一种选择是给自己一个过滤函数,让所有这些结果都通过,这样就可以使用常见的错误处理代码。

但是:您可能会考虑使用“promisifies”节点式回调的库,这样您就可以改用 promises,并使用它们的链式机制完成,这使得集中式错误处理成为可能。 (一个这样的包是 promisify ,但还有其他包。)使用 client.selectclient.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 调用out,而是在模块级别执行:

const redis = require('redis')
module.exports = {
// ...
}

关于javascript - 在异步回调中捕获尝试错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45975402/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com