最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

在 try...catch 块中使用函数如何退出块?

网站源码admin31浏览0评论

在 try...catch 块中使用函数如何退出块?

在 try...catch 块中使用函数如何退出块?

在使用 Node.js 和 express 创建一些端点时,我遇到了一段代码,该代码在不同端点的同一控制器文件中重复了几次。此代码位于 try...catch 块内的条件内,它用于验证数据库中是否存在发送的参数,因此,如果存在或不存在,则执行相应地进行。这是我的原始代码:

const productListing = async (req, res) => {
    const { category_id } = req.query;
    try {
        // if there are query params execute this if statement
        if (req.url.includes("?")) {
            // the next 3 lines of code repeat a few times throughout the controller

            const validCategory = await knex("categories").where("id", category_id)
            if (validCategory.length === 0) {
                return res.status(404).json({ "message": "Category not found" });
            };

            const productsByCategory = await knex("products").where({ category_id })
            return res.status(200).json(productsByCategory);
        }; 

        const allProducts = await knex("products")
        return res.status(200).json(allProducts);
    } catch (error) {
        return res.status(500).json({ "message": "Internal error" });
    };
};

为了改进代码并避免重复我尝试创建下面的函数并调用它而不是重复的代码,我期望得到的是类似的行为,但是尽管该函数在没有发送查询参数时工作,或者当类别存在,当类别不存在时,它会使节点崩溃并且不会给出正确的返回,因为在这种情况下函数应该完成 try...catch 块但是节点尝试在函数有之后设置标题已经做到了。

功能:

const validId = async (res, table, id) => {
    const validateId = await knex(table).where({ id })
        if (validateId.length === 0) {
            return res.status(404).json({ "message": `${table} not found` });
        };
    return 
};

主要代码:

const productListing = async (req, res) => {
    const { category_id } = req.query;
    try {
        if (req.url.includes("?")) {
            validId(res, "categories", category_id);

            const productsByCategory = await knex("products").where({ category_id })
            return res.status(200).json(productsByCategory);
        }; 

        const allProducts = await knex("products")
        return res.status(200).json(allProducts);
    } catch (error) {
        return res.status(500).json({ "message": "Internal error" });
    };
};

错误代码:

    > nodemon ./src/index.js
    
    [nodemon] 2.0.22
    [nodemon] to restart at any time, enter `rs`
    [nodemon] watching path(s): *.*
    [nodemon] watching extensions: js,mjs,json
    [nodemon] starting `node ./src/index.js`
    node:internal/errors:490
        ErrorCaptureStackTrace(err);
        ^
    
    Error [ERR_HTTP_HEADERS_SENT]: Cannot set headers after they are sent to the client
        at new NodeError (node:internal/errors:399:5)
        at ServerResponse.setHeader (node:_http_outgoing:663:11)
        at ServerResponse.header (D:\CODING\CUBOS\BACKEND\unidade-5\desafio-backend-final-dbe-b2b-t03-ifood\node_modules\express\lib\response.js:794:10)
        at ServerResponse.send (D:\CODING\CUBOS\BACKEND\unidade-5\desafio-backend-final-dbe-b2b-t03-ifood\node_modules\express\lib\response.js:174:12)
        at ServerResponse.json (D:\CODING\CUBOS\BACKEND\unidade-5\desafio-backend-final-dbe-b2b-t03-ifood\node_modules\express\lib\response.js:278:15)
        at validaId (D:\CODING\CUBOS\BACKEND\unidade-5\desafio-backend-final-dbe-b2b-t03-ifood\src\funcoes\validaId.js:6:36)
        at process.processTicksAndRejections (node:internal/process/task_queues:95:5) {
      code: 'ERR_HTTP_HEADERS_SENT'
    }
    
    Node.js v18.15.0
    [nodemon] app crashed - waiting for file changes before starting...
回答如下:

The

return res.status(404).json({ "message": `${table} not found` });

validId
函数中实际上是将响应发送给客户端,但它永远不会中断函数的执行,因此它会继续下一个

return res.status(200).json(allProducts);

并抛出,因为响应已经发送。如果我们保持当前状态,您将需要一些方法来确定

validId
函数已经发送了响应。您可以利用
res.headersSent
属性做一些事情,而不必更改太多代码。

const productListing = async (req, res) => {
    const { category_id } = req.query;
    try {
        if (req.url.includes("?")) {
            validId(res, "categories", category_id);
            if(res.headersSent) return;
            const productsByCategory = await knex("products").where({ category_id })
            return res.status(200).json(productsByCategory);
        }; 

        const allProducts = await knex("products")
        return res.status(200).json(allProducts);
    } catch (error) {
        return res.status(500).json({ "message": "Internal error" });
    };
};

如果您将

validId
函数的职责限制在相当大的范围内,并将响应处理留给
productListing
函数,我认为事情会变得更加清晰。

const validId = async (res, table, id) => {
    const validateId = await knex(table).where({ id })
    return validateId.length >= 0;
};

const productListing = async (req, res) => {
    const { category_id } = req.query;
    try {
        if (req.url.includes("?")) {
            if(!validId(res, "categories", category_id)) {
                return res.status(404).json({ "message": `Category not found` })
            }
            const productsByCategory = await knex("products").where({ category_id })
            return res.status(200).json(productsByCategory);
        }; 

        const allProducts = await knex("products")
        return res.status(200).json(allProducts);
    } catch (error) {
        return res.status(500).json({ "message": "Internal error" });
    };
};
发布评论

评论列表(0)

  1. 暂无评论