关于 express 中使用 mongodb 第二次失败问题

- 问题描述

最近在学习使用 express 和 mongodb;
做了demo例子,发现个问题,就是每次从页面上发送请求往表里添加数据时,第一次正常,第二次就报错了?

- 对应代码

  • express 版本 4.16.4
  • mongodb 版本 3.1.10
// express
const express = require('express')
const bodyParser = require('body-parser')
const app = express()
// mongodb
const urlDB = 'mongodb://localhost:27017'
const MongoClient = require('mongodb').MongoClient
const Client = new MongoClient(urlDB, { useNewUrlParser: true })
// mongodb function
const insertDoc = function(db, collectionName, data, callback) {
  const collection = db.collection(collectionName)
  collection.insertOne(data, (err, res) => {
    callback && callback(err, res)
  })
}

app.use(bodyParser.urlencoded({ extended: true }))
// 使用虚拟目录的静态服务
app.use('/static', express.static('public'))
// 路由
app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html')
})
// 应用
app.post('/insert', (req, res) => {
  // mongodb
  Client.connect((err) => {
    const db_ = Client.db('user')
    console.log('-连接成功-', err);
    insertDoc(db_, 'user', req.body, (errDB, resDB) => {
      if (errDB) {
        console.log('-插入失败-', errDB);
        res.send({succ: false})
      } else {
        resDB.result.ok && res.send({succ: true})
        Client.close()
      }
    })
  })
})
// 端口号
app.listen(3000)

- 错误代码

the options [servers] is not supported
the options [caseTranslate] is not supported
-连接成功- null
-插入失败- { MongoError: server instance pool was destroyed
    at basicWriteValidations (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb-core@3.1.9@mongodb-core/lib/topologies/server.js:700:41)
    at Server.insert (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb-core@3.1.9@mongodb-core/lib/topologies/server.js:805:16)
    at Server.insert (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb@3.1.10@mongodb/lib/topologies/topology_base.js:321:25)
    at insertDocuments (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb@3.1.10@mongodb/lib/operations/collection_ops.js:838:19)
    at insertOne (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb@3.1.10@mongodb/lib/operations/collection_ops.js:868:3)
    at executeOperation (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb@3.1.10@mongodb/lib/utils.js:420:24)
    at Collection.insertOne (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb@3.1.10@mongodb/lib/collection.js:464:10)
    at insertDoc (/Users/chisecj/Documents/project/study/test_node/09_express/app.js:12:14)
    at Client.connect (/Users/chisecj/Documents/project/study/test_node/09_express/app.js:30:5)
    at result (/Users/chisecj/Documents/project/study/test_node/09_express/node_modules/_mongodb@3.1.10@mongodb/lib/utils.js:414:17) name: 'MongoError', [Symbol(mongoErrorContextSymbol)]: {} }
阅读 3.5k
2 个回答

Client.close()
你都把client关闭了,第二次来当然要报错了。去掉就好。
MongoClient对象应该在整个生命周期内保持单例,退出应用前都不要关闭,也不应该关闭,因为它还维护着连接池,一旦关闭下次再开需要重建连接,非常浪费资源和降低效率。所以你下面那种写法也是不对的。

重新看了遍文档,理了理逻辑,发现是自己的用法和理解出错了!

  • 按照官方实例其实应该每次连接都要创建新的实例,而不是只创建一个;
  • 就像答1说的那样我把唯一的实例关了,所以只好报错了;
  • 所以应该把 new MongoClient 移到路由内就好了;
app.post('/insert', (req, res) => {
  // mongodb
  const Client = new MongoClient(DBurl, { useNewUrlParser: true })
  Client.connect((err) => {
    const db_ = Client.db('user')
    console.log('-连接成功-', err);
    insertDoc(db_, 'user', req.body, (errDB, resDB) => {
      if (errDB) {
        console.log('-插入失败-', errDB);
        res.send({succ: false})
      } else {
        resDB.result.ok && res.send({succ: true})
        Client.close()
      }
    })
  })
})
  • 再或者就是换种写法,不在新建实例直接使用
app.post('/insert', (req, res) => {
  // mongodb
  MongoClient.connect(DBurl, { useNewUrlParser: true }, (err, client) => {
    // console.log('client--', client);
    const db_ = client.db('user')
    console.log('-连接成功-', err);
    insertDoc(db_, 'user', req.body, (errDB, resDB) => {
      if (errDB) {
        console.log('-插入失败-', errDB);
        res.send({succ: false})
      } else {
        resDB.result.ok && res.send({succ: true})
        client.close()
      }
    })
  })
})
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题