You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Mongoose首次创建Post成功第二次失败,Promise无reject却触发catch?

问题原因分析
  • 核心触发原因:你在create方法内部重复注册了同名Mongoose模型。Mongoose不允许覆盖已经编译完成的模型,第一次执行mongoose.model('Post', postSchema)时会完成Post模型的注册,第二次调用create方法时再次执行该注册逻辑,会直接抛出同步错误。而Promise执行器函数内部的同步错误会被自动捕获,将Promise状态置为rejected,因此哪怕你没有手动调用reject(),也会触发外层的catch回调。
  • 额外存在的逻辑问题:
    1. 验证失败分支未调用reject(),会导致验证不通过时Promise一直处于pending状态,无法触发后续回调。
    2. 验证逻辑存在参数匹配错误:你实例化Post时传入的第一个参数是req.body.text(字符串类型),但validate方法中判断的是this.data.text,对字符串取text属性永远返回undefined,你的非空验证逻辑实际永远不会生效。
    3. save操作未做错误处理,数据库写入失败时无法捕获异常。
修复方案

将Schema定义和模型注册逻辑移到模块顶层,仅执行一次,同时修复上述逻辑问题,修改后代码如下:

// Post.js file
const mongoose = require('mongoose')

// 模型定义移到顶层,全局仅注册一次
const postSchema = new mongoose.Schema({
    body: String,
    author: String,
})
const PostModel = mongoose.model('Post', postSchema)

let Post = function(data, user) {
    this.data = data
    this.username = user
    this.errors = []
}

Post.prototype.validate = function() {
    // 修复验证逻辑,直接判断传入的文本内容
    if (this.data == "") {
        this.errors.push("Cannot be left blank")
    }
}

Post.prototype.create = function() {
    return new Promise((resolve, reject) => {
        this.validate()
        if (!this.errors.length) {
            const post = new PostModel({
                body: this.data,
                author: this.username
            })
            // 增加save操作的错误处理
            post.save((err) => {
                if (err) return reject(err)
                resolve()
            })
        } else {
            // 验证失败主动抛出错误
            reject(this.errors)
        }
    })
}

module.exports = Post

内容的提问来源于stack exchange,提问作者Justin Christopher Domingo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.04 18:15:01