nodejs mysql查询在循环中返回

qcuzuvrc  于 2021-06-19  发布在  Mysql
关注(0)|答案(2)|浏览(379)

我试图创建一个函数,将生成4个唯一的id(十六进制)插入到我的数据库。我将查询放入do while循环中以检查冲突,如果代码已经存在,则重新生成代码,如果没有,则返回值。
问题是循环在预期的时间之前退出。例如,如果代码“a”已生成,但已在数据库中显示,则代码将重新生成,但循环将退出,并且不会进行新的查询。不会返回新代码-而是返回生成的第一个代码。
这是我的密码:

const FIND_EXISITNG_COURT =
  "SELECT access_code,team1,team2 FROM courts WHERE access_code= ?";

function generateAccessCode() {

  var random = Math.floor(Math.random() * (+30 - +0)) + +0;
  var code = random.toString(16);

  var hasDupe = false;

  do {
      connection.query(FIND_EXISITNG_COURT, [code], (err, results) => {

          if (err) {
              throw err;
          } else if (results.length > 0) {
              random = Math.floor(Math.random() * (+30 - +0)) + +0;
              code = random.toString(16);

              hasDupe = true;
          } else {
              hasDupe = false;
          }
      });
  } while (hasDupe);

  return code;
}

我对nodejs是个新手,所以我不知道这样做是否不好。任何帮助都将不胜感激!

6ovsh4lw

6ovsh4lw1#

你的电话 connection.query 是异步的,这意味着您定义的回调不会立即运行。您的代码只是注册回调,然后继续执行,直到结束 generateAccessCode . 回调直到很久以后才被调用(当db返回一些东西时),所以 hasDupe 仅在原始函数退出后很长时间内设置。
您基本上有3个选项来处理这个问题:回调、承诺或异步/等待(这实际上只是承诺之上的语法糖)。
使用async/await但试图尽可能接近原始结构的示例(多次运行以查看其工作情况):

// this is a mock for the db call. This "database" already holds records with IDs 0, 2 and 3.
// IRL you will need to wrap your db call in a function that returns a promise
// if you want to do it this way
const connectionQuery = function (code) {
  return new Promise((resolve) => {
    setTimeout(() => resolve(code === 1 ? [] : [true]), 1000);
  });
}

async function generateAccessCode() {
  // simplified the code generation for this example
  let code = Math.floor(Math.random() * 4); // Code can be 0, 1, 2, or 3

  let hasDupe = false;
  let results;
  do {
      results = await connectionQuery(code); // await here is the key
      if (results.length > 0) {
        console.log(`Code ${code} already exists in the database. Generating new code...`);
        code = Math.floor(Math.random() * 4);           
        hasDupe = true;
      } else {
        hasDupe = false;
      }      
  } while (hasDupe);

  return code;
}

generateAccessCode()
  .then((code) => {
    console.log(`Final result: ${code}`);
  })
  .catch((err) => {
    console.log(err);
  });

改为使用回调:

// this is a mock for the db call. This "database" already holds records with IDs 0, 2 and 3.
const connectionQuery = function (code, callback) {
  setTimeout(() => {    
    callback(null, code === 1 ? [] : [true]);
  }, 1000);
}

function generateAccessCode(callback) {
  // simplified the code generation for this example
  let code = Math.floor(Math.random() * 4); // Code can be 0, 1, 2, or 3

  let hasDupe = false;
  let results;

  connectionQuery(code, (err, results) => {
    if (err) {
      return callback(err);
    }

    if (results.length) {
      console.log(`Code ${code} already exists in the DB`);
      return generateAccessCode(callback);
    }

    callback(null, code);
  });
}

generateAccessCode((err, code) => {
  console.log(`Final result: ${code}`);
});
e0bqpujr

e0bqpujr2#

在代码中,回调函数 query 将在数据准备就绪后运行,因此 hasDupefalse 在第一时间和生成的代码将被返回。
你可以用 Promise 以及 async 函数来解决您的问题

const FIND_EXISITNG_COURT =
"SELECT access_code,team1,team2 FROM courts WHERE access_code= ?";

function selectByCode(code) {  
    return new Promise((resolve, reject) => {
        connection.query(FIND_EXISITNG_COURT, [code], (err, results) => {
        if (err) {
            reject(err);
        } else {
            resolve(results.length)
        }
    });
}

async function generateAccessCode() {

    var random = Math.floor(Math.random() * (+30 - +0)) + +0;
    var code = random.toString(16);

    var hasDupe = false;

    let count =0;
    try{
        do {

            count = await selectByCode(code);
            if (count > 0) {
                random = Math.floor(Math.random() * (+30 - +0)) + +0;
                code = random.toString(16);

                hasDupe = true;
            } else {
                hasDupe = false;
            }

        } while (hasDupe);

        return code;
    }
    catch(e){
        throw e;

    }
}

相关问题