Я хочу создать уникальный токен, поэтому я должен проверить, существует ли значение токена в базе данных MongoDB. Я проверяю внутри, если условие, если токен уже существует. Хотя в режиме разработки у меня есть только несколько токенов в базе данных, поэтому случайное значение должно генерировать что-то другое, но после запуска будет много токенов.

Мой вопрос: будет ли условие if ждать, пока база данных запросит и вернет вывод из функции alreadyExists ниже? Или, будучи асинхронным, он опустится и generateToken() снова?

Вот код,

//Function to check if string already exists
function alreadyExists(val) {
  doc.findOne({token: val}).exec(function(err, docObj){
    if(!docObj) return 0; //If token not found, send a false
    else if (err) return 1; //If error or token, send a false value
    else return 1; //If token found, send a true value
  });
}

//Function to generate a random token
function generateToken() {
  var t = Math.floor(((Math.random() * 9) + 1.111)*1000); //Generates number between 1000 and 9999
  if(!alreadyExists(t)) //Check if token not already exists
    return t; //Return the token
  generateToken(); //Call recursively again until unique token is generated
}

Кроме того, правильный ли код для случайного? Я должен сгенерировать число на самом деле между 1111 и 9999 (исключая конец диапазона, хотя в том числе тоже хорошо)

1
Abhishek Pathak 28 Авг 2017 в 08:04

3 ответа

Лучший ответ

Вам следует больше изучить Обещания Javascript, если Вы хотите вызвать асинхронную функцию. Прямо сейчас ваша функция уже вернет undefined в операторе if, потому что у нее не было времени для выполнения, то есть выполнение вашего оператора if всегда if (!false), так как undefined является ложью.
Оберните другую функцию в обещание и используйте нотацию .then(), чтобы поймать значение.

function alreadyExists(val) {
  return new Promise((resolve, reject) => {
    doc.findOne({token: val}).exec(function(err, docObj){
      if(!docObj) resolve(0); //If token not found, resolve falsy value
      else if (err) reject(err) //If error reject
      else return resolve(1); //If token found, resolve truthy value
    });
  });
}

//Function to generate a random token
function generateToken() {
  var t = Math.floor(((Math.random() * 9) + 1.111)*1000); //Generates number between 1000 and 9999
  alreadyExists(t)
  .then((value) => {//.then() waits for promise to resolve
    if(!value){ //Check if token not already exists
      return t; //Return the token
    }else{
      generateToken(); //Call recursively again until unique token is generated
    }
  })
  .catch((err)=>{
    console.log("Error:",err) //catch any thrown errors
  })
}
2
Francisco Flores 28 Авг 2017 в 07:32

Нет, оператор if не будет ждать завершения асинхронной функции. Вы должны будете передать функцию обратного вызова в функцию уже в Exists

function alreadyExists(val, callback) {
  doc.findOne({token: val}).exec(function(err, docObj){
    if(!docObj) callback(0); //If token not found, send a false
    else if(err) callback(1); //If error or token, send a false value
    else callback(1); //If error or token, send a false value
  });
}

//Function to generate a random token
function generateToken(callback) {
  var t = Math.floor(((Math.random() * 9) + 1.111)*1000); //Generates number between 1000 and 9999
  alreadyExists(t, (exists) => {
      if(!exists) callback(t); //Check if token not already exists
      else generateToken(callback); //Call recursively again until unique token is generated
  })
}

Кроме того, вы можете использовать обещания.

2
EKW 28 Авг 2017 в 05:25

Используйте Promise и новую функциональность await / async для блокировки.

//Function to check if string already exists
async function alreadyExists(val) {
  return new Promise(function(reject, resolve){
      doc.findOne({token: val}).exec(function(err, docObj){
        if(!docObj) reject(0); //If token not found, send a false
        else if (err) reject(err); //If error or token, send a false value
        else resolve(1); //If token found, send a true value
      });
  })
}

//Function to generate a random token
function generateToken() {
  var t = Math.floor(((Math.random() * 9) + 1.111)*1000); //Generates number between 1000 and 9999
  if(! await alreadyExists(t)) //Check if token not already exists
    return t; //Return the token
  generateToken(); //Call recursively again until unique token is generated
}
3
h3xc0ntr0l 28 Авг 2017 в 05:49