首页 文章

快速错误处理和异步等待

提问于
浏览
9

在我的Node.js应用程序中,我添加了以下代码来捕获每个未捕获的异常:

process.on('uncaughtException', function (err: Error) {
    try {
        logger.err(err);
    } catch (err) {

    }
});

问题是Express有自己的默认错误处理程序,它捕获每个未捕获的异常 . 现在,Express在Node(process.on)之前捕获了异常,因此我的 Logger 没有到达 . 但是,可以在Express之前添加另一个可以捕获每个异常的错误处理程序:

app.use(logErrors);

function logErrors (err: Error, req: Request, res: Response, next: NextFunction) {
    logger.err(err);
    next(err);
}

这仍然不包括每一个案例 . 每当我用 await 调用 async function 时,都没有例外,但是会返回被拒绝的Promise . 例如:

app.get('/foo', async function (req: Request, res: Response, next: NextFunction) {
    await bar();
});

function bar() {
    throw new Exception();
}

将无法到达我的 logErrors 函数,因为它不会抛出,但会返回被拒绝的Promise .

所以为了修复它,我用另一个函数包装了我的Express HTTP处理程序:

app.get('/foo', wrap(async function (req: Request, res: Response, next: NextFunction) {
    await bar();
}));

function wrap(func: (req: Request, res: Response, next: NextFunction) => void) {
    return async function (req: Request, res: Response, next: NextFunction) {
        try {
            await func(req, res, next);
        }
        catch (err) {
            next(err);
        }
    }
}

next(错误)将错误传递给我的处理程序 . 现在,我设法捕获我的 logErrors 函数的例外 .

我'm almost done. I still have one case in which I can' t grab 错误 . 当我在没有 await 关键字的情况下调用 async function 时会发生这种情况('s sometimes useful to use the same function in two different places in the code, once calling in asynchronously, and once synchronously). So this code won' t捕获错误:

app.get('/foo', wrap(async function (req: Request, res: Response, next: NextFunction) {
    bar();
}));

这里发生的是Express HTTP处理程序将已解析的Promise返回给 wrap 函数 . 依次包装函数未到达 catch 块,因此它不会调用 next(err) 来到我的 Logger .

反过来 bar 函数返回一个被拒绝的Promise,但是没有人等待它的返回值 .

如何以这样的方式更改我的代码我不会以任何未处理的Promise拒绝结束? (只有通用解决方案)

3 回答

  • 1

    还有另一个 process.on 事件,你可以设置一个监听器--unhandledRejection .

    您可以使用它来处理整个代码中的拒绝 .

    NOTE :记得在记录完所需内容后终止进程 . 更多关于这个here .

  • 1

    我找到了一个解决方案:

    app.get('/foo', async function (req: Request, res: Response, next: NextFunction) {
        dontAwait(() => bar());
    });
    
    async function dontAwait(func: () => void) {
       try {
           await func();
       }
       catch (err) {
         logErrors(err);
       }
    }
    
  • 2

    我还有一个案例,我无法发现错误 .

    你可以,但你目前根本没有对结果做任何事情 . 如果您希望触发常用的错误处理程序,则需要 await 它 .

    当我在没有await关键字的情况下调用异步函数时会发生这种情况

    我看不出有什么好的理由 . 但如果你真的想fire and forget the function,你就可以做到 . 您只需要明确处理错误:

    bar().catch(e => logger.err(e));
    

相关问题