javascript - 等待 mysql 数据库查询完成后再继续

标签 javascript mysql node.js

我遇到一个问题,我想等待异步数据库查询及其操作,然后再继续。

我当然可以将操作放在金字塔内,但从长远来看这并不酷,因为有时我必须重复代码。

这是我的示例(由于数据库查询异步,当前当然无法工作):

var level = 5;
var difficulty = 30; //example
let randomDecider = Math.floor(Math.random()*(50+level)+1);
if (difficulty < randomDecider) {
  var type;
  var name;
  var heroid = "";
  dbconn.query("SELECT * FROM owned_heroes WHERE user = ? AND equipped = 1", [req.session.login], function(err, result, fields) {
    heroid = result[0].heroid;
  });
  if (randomDecider > 50) {
    type = "skill";
    var ownedSkills = [];
    var skillsKeys = Object.keys(Skill);
    dbconn.query("SELECT * FROM owned_skills WHERE user = ? AND heroid = ? AND equipped = 1", [req.session.login, heroid], function(err, result, fields) {
      for (var i = 0; i < result.length; i++) {
        ownedSkills.push(result[i].name);
      }
    });
    //Here later I also want to remove ownedSkills from skillsKeys.
    name = skillsKeys[Math.floor(Math.random()*skillsKeys.length)];
  }
  else {
    type = "item";
    var itemsKeys = Object.keys(Item);
    var ownedItems = [];
    dbconn.query("SELECT * FROM owned_items WHERE user = ? AND heroid = ? AND equipped = 1", [req.session.login, heroid], function(err, result, fields) {
      for (var i = 0; i < result.length; i++) {
        ownedItems.push(result[i].name);
      }
    });
    //Here later I also want to remove ownedItems from itemsKeys.
    name = itemsKeys[Math.floor(Math.random()*itemsKeys.length)];
  }
  //Some other code using the type and name variable.

那么有人可以根据这个解释我如何将其转换为有效的东西,比如等待查询后的操作完成然后再继续。 我尝试了 async/await,但目前无法弄清楚。

也非常欢迎对代码提出任何其他建议。
谢谢。

最佳答案

我已经在评论中解释了如何使用 Promise s。我假设您正在使用 mysql NodeJS 程序的库。

首先,为了避免金字塔(或者我们通常所说的回调 hell ),我们可以尝试将异步函数包装到 Promise 中。像这样:

function queryPromise(str, params) { 
  return new Promise((resolve, reject) => {
    dbconn.query(str, params, (err, result, fields) => {
      if (err) reject(err); 
      resolve(result);
    })
  })
}

那么,我只 promise 了重要的部分:

var level = 5;
var difficulty = 30; //example
let randomDecider = Math.floor(Math.random() * (50 + level) + 1);
if (difficulty < randomDecider) {
  var type;
  var name;
  var heroid = "";

  queryPromise("SELECT * FROM owned_heroes WHERE user = ? AND equipped = 1", [req.session.login]).then(result => {
    heroid = result[0].heroid;
    if (randomDecider > 50) {
      ........

您也可以使用此功能进行其他查询。可是等等!这不就等于放进金字塔了吗?嗯,它或多或少是相同的,并且通常是这样做的方法,以便您的代码按照我们想要的方式执行。但现在,我们可以链接 Promise 的 .then() s 来自内部的其他查询,并避免进一步缩进代码,这会导致创建回调 hell 。不过,这不是我喜欢做的事情,因为当我们不小心处理时,Promise 链也会带来 hell 。

如果您使用的是 Node 8 或更高版本,请使用 async await是最好的解决方案。考虑async await也使用 Promises,我们可以这样做:

var level = 5;
var difficulty = 30; //example
let randomDecider = Math.floor(Math.random() * (50 + level) + 1);
if (difficulty < randomDecider) {
  var type;
  var name;
  var heroid = "";

  let heroidQuery = await queryPromise("SELECT * FROM owned_heroes WHERE user = ? AND equipped = 1", [req.session.login]);
  heroid = heroidQuery[0].heroid;

  if (randomDecider > 50) {
      ........

现在看起来好多了,不是吗?正如关键字所示,await使您的代码等待从查询中检索结果。只是不要忘记将整个代码包装到 async function() 中。阻止为 await不允许外出async功能。

async function myfunc() {
  var level 5;
  ....

我建议查看诸如mysql2/promise之类的库甚至 sequelize当您对 Promises 感到满意时,它会使用 Promises(或者更好的是,与 async-await 一起使用)

我希望这有帮助。祝你好运!

关于javascript - 等待 mysql 数据库查询完成后再继续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49210653/

相关文章:

java - Selenium-Webdriver NodeJS 等同于 DesiredCapabilities 的 Java 代码

javascript - 可以在 Node.js 中将变量设置为只读吗

javascript - 如何在同一页面上隔离不同的javascript库?

javascript - Bootstrap 4 标签输入 - 仅从预定义列表中添加标签

javascript - webpack2可以像SystemJS一样动态加载模块吗

mysql - (2059 ,“Authentication Plugin ' caching_sha2_password'”) 在 Django 上运行与 MYSQL 数据库连接的服务器时

java - 手动更改后恢复数据库记录

javascript - 获取 React JS 私有(private)方法的最佳实践是什么?

mysql - 如何存储非英文字符?

javascript - 在 hooks.js 文件中添加 BeforeScenario 时,Selenium-cucumber.js 测试无法运行