首页 > 解决方案 > 在 ExpressJS 响应中返回异步等待 try/catch 抛出错误

问题描述

使用 ExpressJS4.16.010.15.0NodeJS 和 KnexJS/Bookshelf,我试图弄清楚错误处理。

在我的应用程序中按预期捕获了错误,但服务器调用的响应中没有返回错误:return res.status(400).send(error);,而是我得到了一个{}.

我怎样才能解决这个问题?

用户路线:

router.post('/users/register',
  async function(req, res, next) {

    let user;

    try {
        user = await UserService.register(req.body);
    } catch (error) {
        console.log('Route: Catch: ', error); // Will display error from UserService Error here: "column users.emailll does not exist"

        return res.status(400).send(error); // Sends `{}` back
    }
    ...

用户服务:

...

try {
    user = await new User.User({
        emailll: userInput.email // Will throw error in "catch" below because "emailll" is invalid field
    }).fetch();
} catch (error) {
    // Throws error "column users.emailll does not exist"
    console.log('Service: Catch: ', error);
    throw new Error(error);
}

来自服务器的响应:{}

我假设由于async await调用而在某处吞下了错误?我是否需要使用类似express-async-errors lib 的东西?

标签: javascriptnode.jsexpresserror-handling

解决方案


res.send(err)将在内部尝试将该对象转换为 JSON。默认情况下,JSON.stringify(obj)仅包括目标对象上的可枚举属性,并且您在错误对象上查找的常用属性默认情况下不可枚举。

一种解决方法是使用您要发送的任何属性制作对象的副本,并且通常分配它们将默认为可枚举:

let obj = {filename: error.filename, message: error.message};
res.send(obj);

通常,您不希望将有关服务器的内部详细信息作为错误消息发回,因此通常会隐藏实现细节并发送可能对客户端更有用的消息。

所以,也许你只是想做:

res.status(500).send(error.message);

如果你真的想要err对象的所有属性,你也可以使用这样的辅助函数:

function makeEnumerableCopy() {
    let descriptor = Object.getOwnPropertyDescriptors(err);
    // set all properties in the descriptor to be enumerable
    for (let key of Object.keys(descriptor)) {
        descriptor[key].enumerable = true;
    }
    return Object.defineProperties({}, descriptor);
}

这将制作对象的浅表副本并使所有“自己的”属性都是可枚举的,因此您可以将其与res.send()or一起使用JSON.stringify()并获取所有属性。

res.send(makeEnumerableCopy(err));

推荐阅读