【问题标题】:.save() is not a function (Mongoose).save() 不是函数(猫鼬)
【发布时间】:2021-07-14 06:19:36
【问题描述】:

所以,我不是 100% 为什么这没有按预期工作。我有一个 Edit Profile React 组件(我目前正在学习如何使用 MERN 堆栈构建基于 SSR 的应用程序)-但是当我提交编辑时,我收到一个错误 "user.save is not a功能 - 代码:

从路线:

    router.route('/api/users/:userId')
    .get(authCtrl.requireSignin, userCtrl.read)
    .put(authCtrl.requireSignin, authCtrl.hasAuthorization, userCtrl.update)
    .delete(authCtrl.requireSignin, authCtrl.hasAuthorization, userCtrl.remove)

API 助手:

const update = async (params, credentials, user) => {
  try {
    let response = await fetch('/api/users/' + params.userId, {
      method: 'PUT',
      headers: {
        "Accept": 'application/json',
        Authorization: 'Bearer ' + credentials.t
      },
      body: user
    })
    return await response.json()
  } catch (err) {
      console.log(err)
  }
}

最后是处理更新背后所有逻辑的实际控制器:(此函数在将密码信息传递回客户端之前对其进行清理,因此未定义)

const update = (req, res) => {
  let form = new formidable.IncomingForm()
  form.keepExtensions = true
  form.parse(req, async (err, fields, files) => {
    if (err) {
      return res.status(400).json({
        error: "Photo could not be uploaded"
      })
    }
    let user = req.profile
    user = extend(user, fields)
    user.updated = Date.now()
    if(files.photo){
      user.photo.data = fs.readFileSync(files.photo.path)
      user.photo.contentType = files.photo.type
    }
    try {
      await user.save()
      user.hashed_password = undefined
      user.salt = undefined
      res.json(user)
    } catch (err) {
      console.log(err)
      return res.status(400).json({
        error: errorHandler.getErrorMessage(err)
      })
    }
  })
}

这不是一个生产级应用程序,只是为了让我从头开始学习如何做到这一点(没有 CRA,并且全部包含在一个使用 SSR 的项目中)

编辑:经过一番挖掘,console.logs 和 console.dirs,我发现从组件传递的更新甚至没有传递给控制器​​。过时的数据(来自数据库)正在记录,但 req.profile 完全为空。我可能会完全重新访问此代码并对其进行一些重大更改。所有学习的一部分,对吧?

以下是请求的身份验证方法(我现在使用的是 Session Storage,但可能会更改为 localStorage):

import User from '../models/user.model'
import jwt from 'jsonwebtoken'
import expressJwt from 'express-jwt'
import config from './../../config/config'

const signin = async (req, res) => {
  try {
    let user = await User.findOne({email: req.body.email})
    if (!user) {
      return res.status(401).json({error: "User not found"})
    }
    if (!user.authenticate(req.body.password)) {
      return res.status(401).send({error: "Email and Password do not match"})
    }

    const token = jwt.sign({_id: user._id}, config.jwtSecret)

    res.cookie('t', token, {expire: new Date() + 9999})

    return res.json({
      token,
      user: {
        _id: user._id,
        name: user.name,
        email: user.email
      }
    })
  } catch (err) {
    return res.status(401).json({error: "Could not sign in"})
  }
}

const signout = (req, res) => {
  res.clearCookie('t')
  return res.status(200).json({message: "Signed out"})
}

const requireSignin = expressJwt({
  secret: config.jwtSecret,
  algorithms: ['sha1', 'RS256', 'HS256'],
  userProperty: 'auth'
})

const hasAuthorization = (req, res, next) => {
  const authorized = req.profile && req.auth
  && req.profile._id == req.auth._id
  if (!(authorized)) {
    return res.status(403).json ({error: "User is not authorized"})
  }
  next()
}


export default {
  signin,
  signout,
  requireSignin,
  hasAuthorization
}

【问题讨论】:

  • 你能贴出这两种方法的代码吗? authCtrl.requireSigninauthCtrl.hasAuthorization

标签: node.js reactjs mongodb mongoose mern


【解决方案1】:

可能出错的地方:(代码未显示)

如果你的 req.profile 不是 mongoose 对象,这将不起作用

let user = req.profile

从您的其他帖子中,我认为您可能会从您的 jwt 获得 req.profile。这意味着这不是猫鼬对象。您需要做的是:

  • 正如您提到的,使用findByIdAndUpdate 传递id 和要更新的对象。请注意,如果您有 save 的 mongoose 中间件,它将不会在此处运行

  • 执行user = await User.findById(id),根据您的需要更新用户,然后使用user.save。这使您可以对其进行更多控制,但会运行 2 个操作。

【讨论】:

  • req.profile 来自客户端的表单提交,然后应该通过 PUT 方法(更新配置文件)将其发送到数据库。我在一个单独的答案中发布了提交操作.. 仍然试图从作者的角度思考 SO 的工作原理。通常我只是查一下,哈哈
  • 经过进一步研究, findByIdAndUpdate 会比简单的 PUT 更合适吗?
  • @MikePhelps 你把事情搞混了。 PUTfindByIdAndUpdate 并不相互排斥,它们是可以/应该一起使用的非常不同的东西。在您设置req.profile 的位置发布代码。每个问题都应该有与之相关的代码
  • @MikePhelps 我已经更新了我的答案,应该是你需要的
  • 我想我可能已经找到了罪魁祸首..更多的日志记录等等,事实证明我的提交操作中没有填充 FormData,所以 req.body 被作为空传递,所以目前它没有对数据做任何事情..一旦我把它整理好,我想我可以保存工作,因为我可以获得 req.params 和 req,params.userId,所以 findById()返回正确的记录..
【解决方案2】:

这已经解决了。我的问题显然是表单没有将请求正文正确传递给 API,这是由于依赖项安装错误引起的。一旦我解决了这个问题,其余的就都到位了,我现在可以轻松地做我需要做的事情了..

感谢所有尝试与我一起解决此问题的人。

【讨论】:

    猜你喜欢
    • 2017-03-28
    • 2021-02-10
    • 1970-01-01
    • 2018-01-15
    • 2019-01-18
    • 1970-01-01
    • 2016-06-14
    • 1970-01-01
    • 2017-05-08
    相关资源
    最近更新 更多