【问题标题】:Node JS/Express RoutingNode JS/Express 路由
【发布时间】:2019-11-24 18:56:47
【问题描述】:

我需要一些关于在我的 Node/Express 应用中进行路由的指导。最初,我从业务模型创建了一个新业务(工作正常)。创建业务后,我想要一条单独的路线来添加该业务提供的当前外汇汇率(这些字段将每天更新)。我的商业模式看起来像这样(为了示例而简化):

let businessSchema = new mongoose.Schema({
   name: String,
   category: String,
   longDescription: String,
   images: [ {url: String, public_id: String} ],

   usdHkd: { type: String, default: "" },
   hkdUsd: { type: String, default: "" },
   rateCreatedAt: {
      type:Date,
      default:Date.now
   },
});

首次创建业务时,仅填充名称、类别、longDesc 和图像,并使用外汇汇率字段的默认值。使用这些路线效果很好:

/* GET business new /business/new */
router.get("/new", isLoggedIn, asyncErrorHandler(businessNew));

/* POST business create /business */
router.post('/', isLoggedIn, upload.fields([{ name: 'images', maxCount: 10 }]), asyncErrorHandler(businessCreate));

然后我像这样设置单独的路线/控制器,以便随后添加外汇汇率,但我认为这些定义不正确:

/* GET business index /business */
router.get('/:id/remittance/new', asyncErrorHandler(remittanceNew));

/* GET business index /business */
router.put('/:id/remittance', asyncErrorHandler(remittanceCreate));

    //Remittances New
    async remittanceNew (req, res, next) {
        let business = await Business.findById(req.params.id);
        res.render('remittanceViews/newRemittance', { business }); 
    },

    //Business Update
    async remittanceCreate (req, res, next) {

        let business = await Business.findByIdAndUpdate(req.params.id, req.body.business);
        console.log(business);

        //update the post with any new properties
        business.usdHkd = req.body.business.usdHkd;
        business.hkdUsd = req.body.business.hkdUsd;
        business.rateCreatedAt = req.body.business.rateCreatedAt;

        //save the updated post in the db
        business.save();
        //redirect to show page
        res.redirect(`/business/${business.id}`);
    },

我尝试更新时收到的错误消息是:

Cannot read property 'usdHkd' of undefined

谁能告诉我这里哪里出错了?谢谢

【问题讨论】:

  • req.body.business.usdHkd -- 你使用的是什么正文解析器?您应该注意 Express by default 不解析 POST 正文,您需要使用 3rd 方中间件(甚至由 Express 开发人员编写)来解析 POST 正文。此外,并非所有 bodyparsers 都通过 req.body 传递数据。我知道至少有人使用req.fields
  • @slebetman 我正在使用 body-parser 1.18.3。我在整个应用程序中使用 req.body 没有问题,所以我不确定为什么在这条路线中无法识别它;事实上,即使我从后端给 usdHkd 一个值,然后尝试使用新值进行更新,我仍然得到相同的无法读取未定义错误的属性“usdHkd”。所以我不太清楚究竟什么是未定义的,因为 business.usdHkd 确实已经具有价值。谢谢
  • 好的。知道 body-parser 无法解析 JSON 意味着您正在通过 ether x-www-urlencoded 或表单数据传递请求参数。无论哪种方式,常规请求参数都是简单的键/值对。这意味着req.body.business.usdHkd 没有意义。它应该是req.body.usdHkd 或类似的东西。如果您正在传递 JSON,那么您需要为该 url 使用不同的正文解析器
  • 我的主要业务更新路线是这样的:``` let business = await Business.findByIdAndUpdate(req.params.id, req.body.business); business.name = req.body.business.name; business.category = req.body.business.category; business.longDescription = req.body.business.longDescription; ``` 这工作正常,所以我不清楚为什么我不应该在这条额外的路线中关注 req.body.business.xxx 以获取外汇汇率?
  • req.body.business.name 过得怎么样?浏览器通常无法执行此操作,除非您通过将数据作为 JSON 传递来手动执行此操作。您的代码中是否有其他中间件将req.body.businessName 重新格式化为req.body.business.name?您是否通过 JSON 传递数据?可以显示客户端代码或 Postman/curl 截图/命令吗?

标签: javascript node.js express mongoose


【解决方案1】:

错误信息表明usdHkd 的父变量在未定义。很可能,此错误来自business.usdHkd = req.body.business.usdHkd; 中的business.usdHkd(您可以通过在此行周围添加更多console.log() 行并检查输出来确认)。

如果business.usdHkd = req.body.business.usdHkd; 给出错误,这意味着business未定义。但是,您不需要此行,因为 business 已由 findByIdAndUpdate 更新。

阅读:Model.findByIdAndUpdate()Promises in Mongoose

//Business Update
async remittanceCreate (req, res, next) {

    let business = await Business.findByIdAndUpdate(req.params.id, req.body.business);
    console.log(business);

    // Below code is not required since findByIdAndUpdate() will update your model
    /*
    //update the post with any new properties
    business.usdHkd = req.body.business.usdHkd;
    business.hkdUsd = req.body.business.hkdUsd;
    business.rateCreatedAt = req.body.business.rateCreatedAt;

    //save the updated post in the db
    business.save();
    */

    //redirect to show page
    res.redirect(`/business/${business.id}`);
},

更新

您告诉过business 已定义,但尚未更新。原因是 findOneAndUpdate() 需要将 new 选项设置为 true 否则 findOneAndUpdate() 返回旧对象(在更新之前 - 在某种意义上)。所以,请将remittanceCreate()的第一行改为:

let business = await Business.findByIdAndUpdate(req.params.id, req.body.business, {new: true});

【讨论】:

  • 感谢@Ashutosh 的回复。业务被明确定义为它返回console.log 中的完整对象。我已尝试按照您上面的建议删除代码,虽然删除后我没有收到错误消息,但数据库中的 FX 字段也没有得到更新。关于为什么会这样的任何想法?谢谢!
  • @Martin 请检查上面的更新。我认为它应该可以解决问题。如果没有,请打印req.body.business 以确保它有正确的数据,并告诉我。谢谢!
  • @AshutoshKS 您注释掉的部分正是该功能的原因。将其注释掉会使该功能无用。他正在这样做:let business = getFromDatabase(); business.usdHkd = newValue; business.save()。注释掉的部分是必要的,不是不重要的
  • AshutoshKS 我已经尝试添加 {new: true} 但它仍然没有将这些字段保存到数据库中。 @slebetman 我还假设我需要该代码块,但是当我将其添加回来时,它是否继续给我无法读取属性“usdHkd”的未定义错误。那么有什么想法会导致这种情况吗? usdHkd 在该阶段未定义,因为该字段尚不存在,因此我正在尝试添加它
  • @Martin 查看我对您问题的评论
猜你喜欢
  • 2020-03-26
  • 1970-01-01
  • 2013-08-22
  • 2016-06-27
  • 1970-01-01
  • 1970-01-01
  • 2017-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多