如何根据另一个查询的结果执行查询? (Express,NodeJS,mysql)

时间:2018-03-23 05:05:49

标签: node.js express asynchronous node-mysql

我正在尝试在对'generateSession'端点进行API调用时生成会话ID。我想确保我没有任何重复的会话ID,因此我查询数据库检查生成的ID是否匹配。如果没有匹配,则ID有效,我进行第二次查询以添加具有所述会话ID的活动用户。

虽然我的第一个查询执行,但'id_is_valid'布尔值永远不会设置为true,因此我的程序会陷入while循环。

我对JavaScript很新,但是从一些研究来看,我很确定问题是由于数据库调用的异步性质。但是,我不知道从那里去哪里。拥有更多js知识的人能为我提供一些方向吗?

谢谢!

var express = require('express');
var router = express.Router();

var myDB = require('../db-connection');

function generateSession() {
    var session_id = '';
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (var i = 0; i < 30; i++) session_id += possible.charAt(Math.floor(Math.random() * possible.length));

    return session_id;
}

router.get('/generateSession', function(req, res){
    var session_id = '';
    var id_is_valid = false;
    while (!id_is_valid){
        session_id = generateSession();

        myDB.query("SELECT * FROM activeUser WHERE session_id = ?", [session_id], function(error, results, field){
            if(error) throw error;
            else{
                if (results.length === 0) is_is_valid = true;
            }
        });
    }

    myDB.query("INSERT INTO activeUser (is_registered, session_id) VALUES (0, ?)", [session_id], function(error, results, fields){
        if (error) res.send('{"success": false}');
        else res.send('{"success": true, "session_id": "' + session_id + '"}');
    });
});

2 个答案:

答案 0 :(得分:0)

从我的代码中可以看出,你想要做的事情基本上是为具有唯一会话ID的登录用户创建一个新的用户会话,同时确保集合中不存在会话ID。 / p>

因此,对此的解决方案可以是第一个查询,以检查Active_Users集合中是否已存在会话ID,如果没有进行保存调用以使用生成的会话ID保存用户。

var express = require('express');
var router = express.Router();

var myDB = require('../db-connection');

function generateSession() {
    var session_id = '';
    var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";

    for (var i = 0; i < 30; i++) session_id += possible.charAt(Math.floor(Math.random() * possible.length));

    return session_id;
}

router.get('/generateSession', function(req, res) {
    var session_id = '';

    myDB.query("SELECT * FROM activeUser WHERE session_id = ?", [session_id], function(error, results, field) {
        if (error) {
            throw error;
        } else {
            if (results.length === 0) {
                //if session id is not present , insert new user
                session_id = generateSession();
                myDB.query("INSERT INTO activeUser (is_registered, session_id) VALUES (0, ?)", [session_id], function(error, results, fields) {
                    if (error) res.send('{"success": false}');
                    else res.send('{"success": true, "session_id": "' + session_id + '"}');
                });
            }
            //else do nothing or inser nothing
        }
    });

});

但理想情况下,如果每次向/generate会话发出请求时都生成一个真正随机的会话ID,是否真的有必要检查集合中的重复项。 现在,如果生成随机ID的逻辑不完美,您可以随时使用shortId之类的模块为您完成工作。这将避免不必要的数据库调用并节省性能,并且您的代码将更加整洁。

答案 1 :(得分:0)

  

虽然我的第一个查询执行,但id_is_valid布尔值永远不会设置为true,因此我的程序会陷入while循环。

这是因为db调用本质上是异步的。如果你运行以下程序,你就会知道它。

'use strict';

let id_is_valid = false;
let count = 0;

while (!id_is_valid) {
  count++;
  console.log(`No of time setTimeout Invoked ${count}`);
  setTimeout(function() { // simulating a db call that takes a second for execution
    id_is_valid = true;
  }, 1000);
}

console.log('This line wont be printed');

<强>输出

  

没有时间setTimeout被调用61415
  没有时间setTimeout被调用61416
  没有时间setTimeout Invoked 61417
  ^ C //我杀了它。

与damitj07一样,我也建议使用像shortId这样的npms来唯一地生成sessionId。这将帮助您消除数据库调用。 但是,如果您的业务逻辑受到限制,并且您需要以当前的方式来编写它。我想我们可以使用async&amp; await

'use strict';

let isFound = false;
let count = 0;

function doDbQuery() {
  return new Promise((resolve, reject) => {
    setTimeout(function () {
      resolve(true);
    }, 2000);
  });
}

async function run() {
  while (!isFound) {
    count++;
    console.log(`No of time setTimeout Invoked ${count}`);
    isFound = await doDbQuery();
  }
  console.log('This line WILL BE printed');
}

run();

<强>输出

  

没有时间setTimeout被调用1
  这行将被打印

对代码进行更改

router.get('/generateSession', async function (req, res) {
  var session_id = '';
  var id_is_valid = false;
  while (!id_is_valid) {
    session_id = generateSession();
    id_is_valid = await checkSessionIdInDb(session_id);
  }

  myDB.query('INSERT INTO activeUser (is_registered, session_id) VALUES (0, ?)', [session_id], function (error, results, fields) {
    if (error) {
      res.send('{"success": false}');
    } else {
      res.send('{"success": true, "session_id": "' + session_id + '"}');
    }
  });
});

function checkSessionIdInDb() {
  return new Promise((resolve, reject) => {
    myDB.query('SELECT * FROM activeUser WHERE session_id = ?', [session_id], function (error, results, field) {
      if (error) {
        return reject(error);
      } else {
        if (results.length === 0) {
          resolve(true);
        }
        resolve(false);
      }
    });
  });