【问题标题】:MongoError: Topology is closed, please connect despite established database connectionMongoError:拓扑已关闭,尽管已建立数据库连接,请连接
【发布时间】:2020-05-13 11:37:02
【问题描述】:

我正在编写一个使用异步数据库请求作为 api 一部分的 Web 应用程序。目前,我有一个等待异步函数返回的异步快速路由。这两个函数都返回布尔值并且都查询数据库。一个可以正常工作,但第二个不能。

这里是 MongoClient 设置:

const MongoClient = require('mongodb').MongoClient;
const uri = config.uri;                         // Contains custom url for accessing database
const client = new MongoClient(uri, { useUnifiedTopology: true}, { useNewUrlParser: true }, { connectTimeoutMS: 30000 }, { keepAlive: 1});

config 来自导入为的文件。

const config = require("./config.js");

并且功能正常。

这里是快速设置:

app.post("/signup", async function(request, response) {
  log("POST request at /signup");

  log("BEFORE UNIQUE USER");
  const isUniqueUser = await validateUniqueUser(request.body.email, request.body.password);
  log(isUniqueUser);
  const status = {
    status: null
  };
  if (isUniqueUser) {
    log("AFTER UNIQUE USER");
    let userCreated = await createPracticeProfile(request.body.email, request.body.password);
    log("user created: " + userCreated);
    if (userCreated) {
      status.status = "user_created";
    }
    response.json(status);
  } else {
    response.json(status);
  }

  console.log("********************************end");
});

控制台输出:

在唯一用户之前

是的(应该是)

在唯一用户之后

MongoError:拓扑已关闭。

用户创建:未定义

***...***结束

这是验证用户是否唯一的函数:

/*  VALIDATE_UNIQUE_USER
USE: ensure user does not have existing profile
PARAMS: email (string), password (string)
RETURN: isUniqueUser (bool)
*/
async function validateUniqueUser(email, password) {
  // connect to database
  const database = await client.connect().catch(err => {
    log("ERROR while connecting to database at: validateUniqueUser");
    console.log(err);
    client.close();
  });

  // database connection failed
  if (!database) {
    return false;
  }

  // connection successful => find user
  let user;
  try {
    user = await database.db("guitar-practice-suite").collection("users").findOne({email: email});
  } catch(err) {
    log("ERROR while finding user in database at: validateUniqueUser");
    console.log(err);
    client.close();
    return false;
  } finally {
    client.close();
    // user not found (unique)
    if (user === null || user === undefined) {
      return true;
    }
    return false;
  }
}

这是将用户插入集合的函数:

/* CREATE_PRACTICE_PROFILE
USE: insert a practice profile into the database
PARAMS: email (string), password (string)
RETURN: userCreated (bool)
*/
async function createPracticeProfile(email, password) {
  // hash password
  let hashedPassword;
  try {
    hashedPassword = await new Promise((resolve, reject) => {
      bcrypt.hash(password, null, null, function(err, hash) {
        if (err) {
          reject(err);
        }
        resolve(hash)
      });
    });
  } catch(err) {
    log("ERROR while hashing password at: createPracticeProfile");
    console.log(err);
    return false;
  }

  // connect to database
  const database = await client.connect().catch(err => {
    log("ERROR while connecting to database at: validateUniqueUser");
    console.log(err);
    client.close();
  });

  // database connection failed
  if (!database) {
    return false;
  }

  // database connection successful => insert user into database
  let insertUserToUsers;
  let insertUserToExercises;
  let insertUserToCustomExercises;
  try {
    insertUserToUsers = await database.db("guitar-practice-suite").collection("users").insertOne({email: email, password: hashedPassword});
    insertUserToExercises = await database.db("guitar-practice-suite").collection("exercises").insertOne({email: email});
    insertUserToCustomExercises = await database.db("guitar-practice-suite").collection("custom-exercises").insertOne({email: email, exercises: []});
  } catch(err) {
    log("ERROR while inserting user into database at: createPracticeProfile");
    console.log(err);
    client.close();
    return false;
  } finally {
    client.close();
    return insertUserToUsers && insertUserToExercises && insertUserToCustomExercises;
  }
}

【问题讨论】:

    标签: node.js mongodb express asynchronous server


    【解决方案1】:

    像下面的例子一样配置你的客户端连接

    var MongoClient = require('mongodb').MongoClient;
    
    var Server = require('mongodb').Server;
    
    var mongoClient = new MongoClient(new Server('localhost', 27017));
    
    mongoClient.open(function(err, mongoClient) {
    
      var db1 = mongoClient.db("mydb");
    
      mongoClient.close();
    });
    

    【讨论】:

    • 我应该提到这一点,配置文件在顶部正确导入,因此可以作为任何其他变量引用。
    • 我看到你没有在你的文件中定义你的 insertUserToUsers 变量。尝试定义它
    • 仍然没有运气
    • 我已将范围缩小到我的快速响应在 mongo 完成之前关闭。我正在适当地更新问题。
    【解决方案2】:

    我找到了问题的解决方案,但我不确定我是否理解其中的原因。 validateUniqueUser 函数的 finally 块中的 client.close()。在 createPracticeProfile 函数中的连接完成插入用户之前,它正在关闭连接。

    当该行被取出时,该功能起作用。

    【讨论】:

    • 对我来说也一样。在MongoDB docs 中似乎很奇怪? ?
    【解决方案3】:

    问题是客户端变量需要重新实例化,

    const client = new MongoClient(uri, { useUnifiedTopology: true}, { useNewUrlParser: true }, { connectTimeoutMS: 30000 }, { keepAlive: 1});
    

    试着把它放在createPracticeProfile、validateUniqueUser等函数的开头

    【讨论】:

      【解决方案4】:

      我遇到了错误

      MongoError: Topology is closed
      

      因为身份验证问题

      MongoEror: Authentication failed
      

      就我而言,问题出在我的数据库的password 上。我的密码只包含数字。

      我把密码改成全字符,两个错误都解决了。

      【讨论】:

        猜你喜欢
        • 2020-04-26
        • 2021-06-21
        • 2020-09-16
        • 2017-05-27
        • 2016-01-16
        • 2016-07-18
        • 2020-11-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多