无法捕获然后处理Express API中的Mongoose / MongoDB错误

Cannot Catch then Handle Mongoose / MongoDB error within Express API

提问人:urfx 提问时间:10/27/2023 最后编辑:urfx 更新时间:10/27/2023 访问量:41

问:

我想让前端知道是否存在验证问题,例如重复的提交 ID。我已经准备好了许多堆栈帖子,并尝试了此代码中的各种解决方案......

简而言之,没有一个 catch 方法捕获错误。就好像 mongo 或猫鼬在我的代码进入 :( 之前扔掉了它

这是我的代码

exports.createFinishedJob = async (req, res) => {

    try {
        console.log('createFinishedJob req.body', req.body);
        const finishedjob = new FinishedJob();
        if (req.body.jobSubmissionId) { finishedjob.jobSubmissionId = req.body.jobSubmissionId };
        if (req.body.customerId) { finishedjob.customerId = new ObjectId(req.body.customerId) };
        finishedjob.finishedjob = req.body.finishedjob;
        if (req.body.other) { finishedjob.other = req.body.other };
        console.log('createFinishedJob', finishedjob);

        let error;
        try {
            await finishedjob.save()
                .catch(err => console.log("HALLO err", err));
            // if (res && doc) {
            //     return res.json(doc);
            // } else {
            //     return doc
            // }
        } catch (err) {
            error = err;
            console.log("createFinishedJob error", error)
        }
    } catch (err) {
        console.error("Something went wrong")
        console.error(err)

    }
};

这是错误:-

(node:85241) UnhandledPromiseRejectionWarning: MongoServerError: E11000 duplicate key error collection: Genaich.processingjobs index: jobSubmissionId_1 dup key: { jobSubmissionId: "1006006" }
    at /Users/urfx/phos-code/genaich/node_modules/mongodb/lib/operations/insert.js:50:33
    at /Users/urfx/phos-code/genaich/node_modules/mongodb/lib/operations/command.js:84:64
    at processTicksAndRejections (internal/process/task_queues.js:95:5)
(node:85241) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). To terminate the node process on unhandled promise rejection, use the CLI flag `--unhandled-rejections=strict` (see https://nodejs.org/api/cli.html#cli_unhandled_rejections_mode). (rejection id: 2)

这是模型

const  mongoose  = require("mongoose");
const  Schema  =  mongoose.Schema;
const {ObjectId} = mongoose.Schema;
const SchemaTypes = mongoose.Schema.Types;
const  finishedjobSchema  =  new Schema(
    {
        customerId: { 
            type: ObjectId,
            ref: "User",
            required: false 
        },
        jobSubmissionId:{
            type: String, // if we don't get one from the customer use payment / order number
            unique: true,
            index: true
        },
        trashed: {
            type: Boolean
        },
        finishedjob: {
            type: Object
        },
        other: {
            type: SchemaTypes.Mixed // to start the ball rolling 
        }

    },
    { timestamps: true });

let  FinishedJob  =  mongoose.model("FinishedJob", finishedjobSchema);
module.exports  =  FinishedJob;
JavaScript 节点 .js 猫鼬 错误处理

评论

0赞 jQueeny 10/27/2023
发布架构。您在 上有一个简单的错误。一旦我看到您的架构,这将很容易调试。E11000 duplicate keyjobSubmissionId
0赞 urfx 10/27/2023
是的,我想要 E11000 错误。我的问题一旦生成,我想捕获错误......并告诉客户端应用程序架构不是问题所在。submissionID 是唯一的和索引的,因此它会根据我的需要工作并抛出错误。或者您建议我在架构中捕获错误?
0赞 jQueeny 10/27/2023
如果存在重复键错误,您是否打算将 json 返回给用户?
0赞 urfx 10/27/2023
@jQueeny我的目标是通过我的 Express API 返回 JSON 消息来处理错误。
1赞 jQueeny 10/27/2023
好。让我看看。

答:

1赞 jQueeny 10/27/2023 #1

选项一是使用该方法并捕获它抛出的任何错误。这就像一个 + 多合一的方法。像这样使用:Model.create()Model.create()const doc = new Model();doc.save()

exports.createFinishedJob = async (req, res) => {
   try {
        // If this fails for any reason it will throw to the catch block
        const finishedjob = await FinishedJob.create({
            jobSubmissionId: req.body.jobSubmissionId,
            customerId: req.body.customerId,
            finishedjob: req.body.finishedjob,
            other: req.body.other
        });
        // This will only return if the document was created successfully
        return res.status(200).json({
            message: 'Job Created'
        });
    } catch (err) {
        console.error(err);
        // Check for the E11000 duplicate key error
        if(err.code === 11000){
            return res.status(400).json({
                message: err.message
            });
        }else{
            return res.status(500).json({
                message: 'Error on server'
            });
        }
    }
};

选项二是快速检查 with 是否已存在,并尽早返回错误消息。但是,如果没有匹配项,那么您仍然需要再次创建新文档,这意味着对数据库的两次调用,因此,如果您每分钟处理对该路由的数千个新请求,那么效率显然会降低。像这样使用:FinishedjobjobSubmissionId

exports.createFinishedJob = async (req, res) => {
    try {
        const existingFinishedjob = await FinishedJob.findOne({
           jobSubmissionId: req.body.jobSubmissionId
        });
        if (existingFinishedjob){
            return res.status(400).json({
                message: 'Already exists'
            });
        }
        const finishedjob = await FinishedJob.create({
            jobSubmissionId: req.body.jobSubmissionId,
            customerId: req.body.customerId,
            finishedjob: req.body.finishedjob,
            other: req.body.other
        });
        return res.status(200).json({
            message: 'Job Created'
        });
    } catch (err) {
        console.error(err);
        return res.status(500).json({
            message: 'Error on server'
        });
    }
};

评论

0赞 urfx 10/27/2023
谢谢你,我今天将测试并恢复。我已经有一个 upsert 样式方法,它检查现有作业,然后使用 create 函数。只是等待咖啡开始。非常感谢您的回答。泰
1赞 urfx 10/27/2023 #2

非常感谢@jQueeny

您使用“create”的第一个建议可以满足我的需求,但我应该稍作调整,我也想返回成功的新文档。我不能把这些都放在评论中。

/**
 * THANKS @jQueeny for this working solution to handling 11000 with a catch
 * using create instead of save... seems I had the clue in my method name to 
 * start with
 * @param {*} req 
 * @param {*} res 
 * @returns duplicate error if the submissionId already exists otherwise returns the new "finished" document
 */
exports.createFinishedJob = async (req, res) => {
   try {
        // If this fails for any reason it will throw to the catch block
        const finishedjob = await FinishedJob.create({
            jobSubmissionId: req.body.jobSubmissionId,
            customerId: req.body.customerId,
            finishedjob: req.body.finishedjob,
            other: req.body.other
        });
        // This will only return if the document was created successfully
        if (res && finishedjob) {
            console.log({"success":finishedjob});
            return res.status(200).json({"success":finishedjob});
        } else {
            return finishedjob
        }
    } catch (err) {
        console.error(err);
        // Check for the E11000 duplicate key error
        if(err.code === 11000){
            return res.status(400).json({
                message: err.message
            });
        }else{
            return res.status(500).json({
                message: 'Error on server'
            });
        }
    }
};