【问题标题】:How to repeatedly execute nodejs mysql query until desire result come out?如何重复执行nodejs mysql查询直到得到期望的结果?
【发布时间】:2019-05-31 17:02:57
【问题描述】:
conn.connect(function (err) {
        if (err) throw err;
        var prizeCode = generatePrizeCode();// this method return a 5-digit code
        var query = "SELECT * FROM user WHERE code = ? ";
        var values = [[prizeCode]];
        conn.query(query, [values], function (err, result) {
            if (err) throw err;
            // Here I want to re-execute the above query if the result is not empty 
        });
    });

在上面的代码中,只要结果包含数据,我就想执行查询。但是我不能像下面的伪代码那样使用循环,

// if the result is empty, the generated code does not exist in database. So it can be used.
while(result.length != 0){
    var result = conn.query("SELECT * FROM user WHERE code = abc");
}

我怎样才能做到这一点?

【问题讨论】:

  • 您想实现什么?如果有任何即将到来,您想重试,或者您想将相同的代码运行到不定数量?
  • @AnoopMc 我想重复执行查询,只要查询结果包含数据(一行或多行)。
  • 您可以创建一个方法,该方法会一直尝试直到结果出现。所以如果有任何错误,基本上ti会再次调用该方法。为避免无限循环,您可以使用计数器的最大重试次数。
  • @AnoopMc 请您详细说明或提供示例链接?
  • 当然,已在答案中添加了代码 sn-p。请修改使用。

标签: javascript mysql node.js database node-mysql


【解决方案1】:

您必须使用回调或承诺/异步函数。以下是如何使用回调编写它:

const mysql = require('mysql');

const retryLimit = 50;

const connection = mysql.createConnection({
  database: 'test',
  host: 'localhost',
  password: 'hunter2',
  user: 'dave',
});

function getData(attempts, cb) {
  if (attempts < retryLimit) { // we haven't exausted our attempts yet
    const code = generatePrizeCode();
    connection.query('SELECT * FROM user WHERE code = ?', code, (err, result) => {
      if (err) {
        return cb(err);
      }
      if (result.length > 0) { // code already exists
        getData(attempts + 1, cb); // recurse
      } else { // this is a new code
        cb(null, code); // return the new code via the callback function
      }
    });
  } else { // we have exausted our attempts
    return cb(new Error('retry limit exceeded'));
  }
}

getData(0, (err, code) => {
  // do what you want here, e.g., console.log(code)
  connection.end();
});

请注意,如果您递归太多次并超过最大调用堆栈,这可能会导致节点崩溃。一种解决方法是调用 setImmediate 或 setTimeout 而不是直接递归。而不是行

getData(attempts + 1, cb); // recurse

使用

setImmediate(() => {
  getData(attempts + 1, cb); // recurse
});

// recurse, using setImmediate every 1000th time
if (attempts % 1000 === 0) {
  setImmediate(() => {
    getData(attempts + 1, cb); // recurse
  });
} else {
  getData(attempts + 1, cb); // recurse
}

使用 Promise 和 async/await 风格会清理很多,看起来更像你习惯的(注意这里使用 promise-mysql 库):

const mysql = require('promise-mysql');

async function getData(connection) {
  const retryLimit = 50;
  for (let i = 0; i < retryLimit; i++) {
    const code = generatePrizeCode();
    const result = await connection.query('SELECT * FROM user WHERE code = ?', code);
    if (result.length === 0) { // this code doesn't exist yet
      return code;
    }
  }
  throw new Error('retry limit exceeded');
}

(async () => {
  try {
    const connection = await mysql.createConnection({
      database: 'test',
      host: 'localhost',
      password: 'hunter2',
      user: 'dave',
    });
    try {
      const code = await getData(connection);
      // do what you want here, e.g., console.log(code)
    } finally {
      connection.end();
    }
  } catch (err) {
    console.log(err);
  }
})();

【讨论】:

    【解决方案2】:

    基本上你需要使用 async\await 或 promises(几乎相同)。 https://javascript.info/async-await https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise

    这样,只有在获得适合您的结果时,您才能返回。

    【讨论】:

      【解决方案3】:

      var mysql = require('mysql');
      var pool  = mysql.createPool({
        host     : 'YOUR_HOST_NAME',
        user     : 'YOUR_USER_NAME',
        password : 'YOUR_PASSWORD',
        database : 'YOUR_DATABASE'
      });
      
      pool.getConnection(function(err, connection) {
        // connected! (unless `err` is set)
      });
      
      
      connection = mysql.createPool
      var retryLimit=0;
      
      var getData = function () {
      if(retryLimit <= 50)
      {
      retryLimit++;
      connection.query('SELECT * FROM user WHERE code = abc', function (error, results, fields) {
        if (error) {throw error;}
        else if(result.length <1) {
      getData();
      //call the same method again.
      }
      });
      }
      }
      
      
      getData();

      您可以添加 else 语句并做任何您想做的事情。

      【讨论】:

      • 如果有一个大号码怎么办。数据库中存在哪些代码的用户?在这种情况下,调用堆栈将变得非常大,并且代码可能会因超出最大调用堆栈大小异常而崩溃。
      • 不要这样做。确实最大。调用堆栈将在这里成为一个问题。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-01
      • 2013-05-13
      • 1970-01-01
      • 2020-05-24
      • 2018-07-03
      相关资源
      最近更新 更多