【问题标题】:MongooseError - Operation `users.findOne()` buffering timed out after 10000msMongooseError - 操作 `users.findOne()` 缓冲在 10000 毫秒后超时
【发布时间】:2021-04-01 03:39:20
【问题描述】:

我的代码最初可以正常工作,但我不知道为什么它停止工作并给了我这个错误:

MongooseError: Operation `users.findOne()` buffering timed out after 10000ms
    at Timeout.<anonymous> (/Users/nishant/Desktop/Yourfolio/backend/node_modules/mongoose/lib/drivers/node-mongodb-native/collection.js:184:20)
    at listOnTimeout (internal/timers.js:549:17)
    at processTimers (internal/timers.js:492:7)

我正在尝试通过使用 JWT 登录来对用户进行身份验证。我的客户端运行良好,但在我的后端出现此错误。我的后端代码:

import neuron from '@yummyweb/neuronjs'
import bodyParser from 'body-parser'
import cors from 'cors'
import mongoose from 'mongoose'
import emailValidator from 'email-validator'
import passwordValidator from 'password-validator'
import User from './models/User.js'
import Portfolio from './models/Portfolio.js'
import bcrypt from 'bcryptjs'
import jwt from 'jsonwebtoken'
import auth from './utils/auth.js'

// Dot env
import dotenv from 'dotenv'
dotenv.config()

// Custom Password Specifications
// Username Schema
const usernameSchema = new passwordValidator()
usernameSchema.is().min(3).is().max(18).is().not().spaces()

// Password Schema
const passwordSchema = new passwordValidator()
passwordSchema.is().min(8).is().max(100).has().uppercase().has().lowercase().has().digits().is().not().spaces()

const PORT = process.env.PORT || 5000
const neuronjs = neuron()

// Middleware
neuronjs.use(bodyParser())
neuronjs.use(cors())

// Mongoose Connection
mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true }, () => console.log("MongoDB Connected"))

// API Routes
neuronjs.POST('/api/auth/signup', async (req, res) => {
    const { username, email, password, passwordConfirmation } = req.body

    // Validation: all fields are filled
    if (!username || !email || !password || !passwordConfirmation) {
        return res.status(400).json({ 
            "error": "true",
            "for": "fields",
            "msg": "fill all the fields"
        })
    }

    // Validation: username is valid
    if (usernameSchema.validate(username, { list: true }).length !== 0) {
        return res.status(400).json({ 
            "error": "true",
            "for": "username",
            "method_fail": usernameSchema.validate(username, { list: true }),
            "msg": "username is invalid"
        })
    }

    // Validation: email is valid
    if (!emailValidator.validate(email)) {
        return res.status(400).json({ 
            "error": "true",
            "for": "email",
            "msg": "email is invalid"
        })
    }

    // Validation: password is valid
    if (passwordSchema.validate(password, { list: true }).length !== 0) {
        return res.status(400).json({ 
            "error": "true",
            "for": "password",
            "method_fail": passwordSchema.validate(password, { list: true }),
            "msg": "password is invalid"
        })
    }

    // Validation: password is confirmed
    if (password !== passwordConfirmation) {
        return res.status(400).json({ 
            "error": "true",
            "for": "confirmation",
            "msg": "confirmation password needs to match password"
        })
    }

    // Check for existing user with email
    const existingUserWithEmail = await User.findOne({ email })
    if (existingUserWithEmail)
        return res.status(400).json({ "error": "true", "msg": "a user already exists with this email" })

    // Check for existing user with username
    const existingUserWithUsername = await User.findOne({ username })
    if (existingUserWithUsername)
        return res.status(400).json({ "error": "true", "msg": "a user already exists with this username" })

    // Generating salt
    const salt = bcrypt.genSalt()
    .then(salt => {
        // Hashing password with bcrypt
        const hashedPassword = bcrypt.hash(password, salt)
        .then(hash => {
            const newUser = new User({
                username,
                email,
                password: hash
            })
            // Saving the user
            newUser.save()
            .then(savedUser => {
                const newPortfolio = new Portfolio({
                    user: savedUser._id,
                    description: "",
                    socialMediaHandles: {
                        github: savedUser.username,
                        dribbble: savedUser.username,
                        twitter: savedUser.username,
                        devto: savedUser.username,
                        linkedin: savedUser.username,
                    }
                })

                // Save the portfolio
                newPortfolio.save()

                // Return the status code and the json
                return res.status(200).json({
                    savedUser
                })
            })
            .catch(err => console.log(err))
        })
        .catch(err => console.log(err))
    })
    .catch(err => console.log(err))
})

neuronjs.POST('/api/auth/login', async (req, res) => {
    try {
        const { username, password } = req.body

        // Validate
        if (!username || !password) {
            return res.status(400).json({ "error": "true", "msg": "fill all the fields", "for": "fields", })
        }

        const user = await User.findOne({ username })
        if (!user) {
            return res.status(400).json({ "error": "true", "msg": "no account is registered with this username", "for": "username" })
        }
    
        // Compare hashed password with plain text password
        const match = await bcrypt.compare(password, user.password)
    
        if (!match) {
            return res.status(400).json({ "error": "true", "msg": "invalid credentials", "for": "password" })
        }
    
        // Create JWT token
        const token = jwt.sign({ id: user._id }, process.env.JWT_SECRET)
        return res.json({ token, user: { "id": user._id, "username": user.username, "email": user.email } })
    }
    catch (e) {
        console.log(e)
    }
})

// Delete a user and their portfolio
neuronjs.DELETE("/api/users/delete", async (req, res) => {
    auth(req, res)
    const deletedPortfolio = await Portfolio.findOneAndDelete({ user: req.user })
    const deletedUser = await User.findByIdAndDelete(req.user)
    res.json(deletedUser)
})

neuronjs.POST("/api/isTokenValid", async (req, res) => {
    const token = req.headers["x-auth-token"]
    if (!token) return res.json(false)
    
    const verifiedToken = jwt.verify(token, process.env.JWT_SECRET)
    if (!verifiedToken) return res.json(false)
    
    const user = await User.findById(verifiedToken.id)
    if (!user) return res.json(false)

    return res.json(true)
})

// Getting one user
neuronjs.GET("/api/users/user", async (req, res) => {
    auth(req, res)
    const user = await User.findById(req.user)
    res.json({
        "username": user.username,
        "email": user.email,
        "id": user._id
    })
})

// Getting the porfolio based on username
neuronjs.GET("/api/portfolio/:username", async (req, res) => {
    try {
        const existingUser = await User.findOne({ username: req.params.username })
        // User exists
        if (existingUser) {
            const userPortfolio = await Portfolio.findOne({ user: existingUser._id })
            return res.status(200).json(userPortfolio)
        }
        // User does not exist
        else return res.status(400).json({ "error": "true", "msg": "user does not exist" })
    }
    catch (e) {
        console.log(e)
        return res.status(400).json({ "error": "true", "msg": "user does not exist" })
    }
})

// Update Portfolio info
neuronjs.POST("/api/portfolio/update", async (req, res) => {
    auth(req, res)

    // Find the portfolio
    const portfolio = await Portfolio.findOne({ user: req.user })
    // Then, update the portfolio
    if (portfolio) {
        // Call the update method
        const updatedPortfolio = await portfolio.updateOne({
             user: req.user, 
             description: req.body.description, 
             socialMediaHandles: req.body.socialMediaHandles, 
             greetingText: req.body.greetingText, 
             navColor: req.body.navColor, 
             font: req.body.font, 
             backgroundColor: req.body.backgroundColor,
             rssFeed: req.body.rssFeed,
             displayName: req.body.displayName,
             layout: req.body.layout,
             occupation: req.body.occupation
            })
        return res.status(200).json(portfolio)
    }
})

neuronjs.listen(PORT, () => console.log("Server is running on port " + PORT))

auth.js 文件函数:

import jwt from 'jsonwebtoken'

const auth = (req, res) => {
    const token = req.headers["x-auth-token"]
    if (!token)
        return res.status(401).json({ "error": "true", "msg": "no authentication token" })
    
    const verifiedToken = jwt.verify(token, process.env.JWT_SECRET)
    if (!verifiedToken)
        return res.status(401).json({ "error": "true", "msg": "token failed" })
    
    req.user = verifiedToken.id
}

export default auth

非常感谢任何帮助,我已经尝试了一些解决方案,例如删除 node_modules 并重新安装 mongoose。

【问题讨论】:

    标签: node.js mongodb mongoose


    【解决方案1】:

    确保您在函数顶部(内部文件)连接到 MongoDB,并在连接到 MongoDB Atlas 后执行 (CRUD) 操作。

    希望这是有道理的。 我收到错误是因为在我的文件中,我正在从其他服务器加载数据并在异步操作之后插入到我的 MongoDB 中,我正在连接到我的 MongoDB 服务器,这就是我收到错误的原因。

    正确

    -

    await mongoose.connect(MONGO_URL, {
             useNewUrlParser: true,
             useUnifiedTopology: true,
           }); await parseAndLoadPlanetsData();
    

    不正确

    -

    await parseAndLoadPlanetsData();
           await mongoose.connect(MONGO_URL, {
             useNewUrlParser: true,
             useUnifiedTopology: true,
           });
    

    【讨论】:

      【解决方案2】:

      当我在服务器出错时尝试使用我的数据库时,我自己也遇到了这个问题,猫鼬创建了一个巨大的 87 部分错误面板,我必须对其进行筛选,当我这样做时,我发现我通过的选项猫鼬被贬值了。因此,如果您可以滚动到启动服务器的位置,您可能会看到告诉您删除或附加某些选项的详细信息。删除额外的选项解决了我的问题。

      【讨论】:

        【解决方案3】:

        我在使用 Mongoose 6 时遇到了同样的问题。我通过以下方式在我的 index.js 文件中连接到 Mongoose:

        mongoose.connect(
          process.env.MONGO_URL,
          { useNewUrlParser: true, useUnifiedTopology: true, useCreateIndex: true },
          () => {
            console.log('Connected to MongoDB');
          }
        );
        

        我在他们的网站上找到了 Mongoose 6 的以下信息:

        useNewUrlParser、useUnifiedTopology、useFindAndModify 和 useCreateIndex 不再是受支持的选项。猫鼬 6 总是 表现得好像 useNewUrlParser、useUnifiedTopology 和 useCreateIndex 为真,而 useFindAndModify 为假。请删除这些选项 来自您的代码。

        当我删除useCreateIndex: true 选项后,问题就解决了。

        【讨论】:

        • 这对我有用。你知道为什么useCreateIndex: true 会惹麻烦吗?
        • 它造成了麻烦,因为它不是 Mongoose 6 中支持的选项,也不应该添加到选项中(就像答案中的引用所说),但我们在选项中有它。
        【解决方案4】:

        我的问题解决了,因为已经有一个集群,我的 mongo db atlas 中的集合,我所要做的就是清除它并发送另一个发布请求以使其工作。

        【讨论】:

          【解决方案5】:

          我遇到了同样的问题。就我而言,我将 mongoose.connect 语句保存在不同的文件中,并在编写 require 语句时忘记调用它。

          require(./services/mongoose);
          

          我已经在我的 index.js 文件中完成了这个并将其更改为这个

          require(./services/mongoose)();
          

          【讨论】:

            【解决方案6】:

            我的代码在一台 PC 上运行正常,但在另一台 PC 上我得到了同样的错误。我有 https://www.mongodb.com/ 的 MongoDB 免费托管。

            我通过将我当前的 IP 添加到托管服务器中的 Security - Network Access - IP Access List 来修复它。

            【讨论】:

            • 网速爬行或您的服务器无法连接到远程数据库也可能是错误的原因。
            【解决方案7】:

            我遇到过很多次了;特别是当我升级了需要猫鼬的嵌套依赖项时。这总是对我有用。

            rm -rf node_modules
            rm package-lock.json
            npm install --package-lock-only
            npm install
            

            【讨论】:

            • 我没有添加第三步,但这是唯一对我有用的东西。显然,当我尝试 npm audit fix 时,我把 mongoose 搞砸了。谢谢你的伎俩。
            • 如果您删除了package-log.json,您应该使用npm install --package-lock-only 重新安装它。有时,两个单独的 npm install 会创建包锁,导致源代码控制系统中的合并冲突。
            【解决方案8】:

            显示此错误[user.findOne()] 是因为您的config 软件包版本已自动更新。

            在终端中输入以下内容:

            npm i -E config@3.3.1
            

            yarn add -E config@3.3.1
            

            【讨论】:

              【解决方案9】:

              mongoose.connect('mongodb://localhost/myapp', {useNewUrlParser: true});

              只需在连接文件中添加{useNewUrlParser: true}

              【讨论】:

              • 查看原问题可以清楚的看到{useNewUrlParser: true}已经被添加了。
              【解决方案10】:

              根据我的经验,当您的数据库未连接时会发生这种情况,请尝试检查以下内容 -

              • 您是否已连接数据库并且您从代码中指向相同的 url。
              • 检查您的mongoose.connect(...) 代码是否正在加载。

              我遇到了这个问题,我从终端运行 node index.js 并且 mongoose 连接代码在不同的文件中。在 index.js 中要求该猫鼬代码后,它又可以工作了。

              【讨论】:

                【解决方案11】:

                根据此链接中的文档:https://mongoosejs.com/docs/connections.html#buffering

                Mongoose 让您可以立即开始使用模型,而无需等待 mongoose 与 MongoDB 建立连接。

                这是因为 mongoose 在内部缓冲模型函数调用。这 缓冲很方便,但也是常见的混淆来源。 如果你使用模型,Mongoose 默认不会抛出任何错误 无需连接。

                TL;DR:

                在建立连接之前调用您的模型。您需要将async/await 与connect() 或createConnection() 一起使用;或者使用.then(),因为这些函数现在从Mongoose 5返回承诺。

                【讨论】:

                  【解决方案12】:

                  创建集群后单击连接并添加您的 IP 或在 MongoDB Atlas 中添加另一个 IP

                  【讨论】:

                    猜你喜欢
                    • 2021-06-30
                    • 2021-08-23
                    • 2021-11-15
                    • 2021-12-08
                    • 2021-04-01
                    • 2021-04-12
                    • 2021-04-11
                    • 1970-01-01
                    • 2022-11-28
                    相关资源
                    最近更新 更多