Запуск логи c с обещанного результата - PullRequest
0 голосов
/ 26 апреля 2020

У меня есть дискорд-бот, который хочет хранить в базе данных идентификаторы пользователей с названиями городов Пользователь введет команду! Storeme [название города], и бот создаст новый документ в коллекции. Например, пользователь с идентификатором 123456789 вводит команду! Storeme London:

{
    "userid": 123456789,
    "cityname": "London"
}

затем сохраняется в коллекции.

Однако я хочу, чтобы у каждого пользователя была только одна запись - и это не может быть изменено. Поэтому, когда пользователь вводит команду, его идентификатор пользователя сравнивается с базой данных, чтобы убедиться, что она еще не связана с городом. Вот где возникает моя проблема.


function checkUserIdInDatabase(userID){
    const collection = db.collection("UserToCity")
    var result = collection.findOne({"userid": userID}, function(err, db){
        return !!result  // True if the user already exists in the database
    })
}

function storeme(user, cityname){
    // Do some data verification stuff here
    if (checkUserIdInDatabase(user.userID)){
       console.log("User already in the database!")
    } else {
       addUserToDatabase(user, cityname)  // This function is known to work
    }
}

Моя проблема в том, что условное if (checkUserIdInDatabase(user.userID)) всегда возвращает false, даже если пользователь существует в базе данных. Если я помещу logi c в анонимную функцию collection.findOne(), он может легко это определить.

Тогда я предполагаю, что проблема в том, что в storeme обещание в checkUserIdInDatabase еще не было был решен.

Мой вопрос: как мне разрешить функции storeme определять, существует ли пользователь в базе данных? Я мог бы переместить collection.findOne() в storeme и запустить все логи c в анонимной функции, но это выглядит очень неуклюже.

Ответы [ 2 ]

1 голос
/ 26 апреля 2020

Запрос к базе данных - это асинхронная задача c. Поэтому вы должны использовать Promise или Async / await для обработки вывода.

В этом случае вам следует переписать checkUserIdInDatabase с таким обещанием.

function checkUserIdInDatabase(userID) {
  return new Promise((resolve, reject) => {
    const collection = db.collection("UserToCity")
    collection.findOne({ "userid": userID }, function (err, result) {
      if (err) {
        reject(err);
        db.close();
      }
      else {
        resolve(!!result);  // True if the user already exists in the database
        db.close();
      }
    });
  });
}

И вызвать его в функции storeme, как.

function storeme(user, cityname) {
  // Do some data verification stuff here
  checkUserIdInDatabase(user.userID)
    .then(res => {
      if (res) {
        console.log("User already in the database!")
      }
      else {
        addUserToDatabase(user, cityname)  // This function is known to work
      }
    })
    .catch(err => {
      // handle error
      console.log(err);
    });
}
0 голосов
/ 26 апреля 2020

Я решил это, обернув функциональность storeme в свою собственную функцию, изменив код так:

function checkUserIdInDatabase(userID){
    const collection = db.collection("UserToCity")
    var result = collection.findOne({"userid": userID}, function(err, db){
        return !!result  // True if the user already exists in the database
    })
}

function addUserToDatabase(user, cityname){
    const collection = db.collection("UserToCity")

    var result = collection.findOne({"userid": userID}, function(err, db){
        if (checkUserIdInDatabase(user.userID)){
           console.log("User already in the database!")
        } else {
           collection.add(user, cityname)
        }
    })

}

function storeme(user, cityname){
    // Do some data verification stuff here
    addUserToDatabase(user, cityname)
    // Any other stuff can be done here
}
...