异步查询node.js中的数据库

时间:2017-11-09 23:05:00

标签: node.js

我试图找出异步调用函数的正确方法,如果它也在对数据库进行异步调用。

在我的代码中,我调用一个名为' check_foods()的函数,如果尚未调用数据库,它将最多查询两次数据库。数据库查询将填充蔬菜和水果这两个变量(假设它们尚未填充)。一旦函数返回,我想利用这些变量。

但是,我假设我的代码现在的方式是它将尝试开始处理两条console行,即使它还没有从数据库中提取数据。我在这个假设中是否正确?如果是这样,我该怎么做才能正确实现?

我的代码的简化版本如下所示:

var vegetables = {};
var fruit = {};


async function starter (){
    sql = "select growth_items from garden where room_id = ?";
    db_connection.query(sql, [socket.room], function (err, result){
        if (err){
            console.log("Garden Error: " + err);
            return;
        }

        console.log(result);

        check_foods();

        //Should not get to this point until variables have been populated
        //However, due to the async nature of the code this does not seem to be implemented correctly. 
        //process vegetables[socket.room] and fruit[socket.room]
        console.log(vegetables[socket.room]);
        console.log(fruit[socket.room]);
    });    
}

async function check_foods(){
       //Check to see if vegetables[socket.room] already exists, otherwise load it from the database
       if (typeof vegetables[socket.room] !== "undefined"){
            sql = "select name, qty from vegetables where room_id = ?";
            db_connection.query(sql, [socket.room], function (err, result){
                if (err){
                    console.log("An vegetable error has occurred: " + err);
                    return;
                }

                vegetables[socket.room] = result;
            });
        };

        //Check to see if fruit already exists before looking up again

        if (typeof fruit[socket.room] !== "undefined"){
            sql = "select name, qty from fruit where room_id = ?";
            db_connection.query(sql, [socket.room], function (err, result){
                if (err){
                    console.log("An fruit error has occurred: " + err);
                    return;
                }

                fruit[socket.room] = result;
            });
        };

}

2 个答案:

答案 0 :(得分:5)

对于像这样的项目来说,将所有内容分解为小单元非常有帮助。这样,可以以更容易推理的方式包含或宣传异步部分。看起来你想使用async/await这对此很好,但这意味着你需要生成promises。上次我检查标准的MySQL库并没有这样做,但它很容易包装它们。

所以我会把它分解为这样:

function check_growth_items(room){
   //simple function to get growth items
    return new Promise((resolve, reject) => {
        sql = "select growth_items from garden where room_id = ?";
        db_connection.query(sql, [room], function (err, result){
            if (err){
                console.log("Garden Error: " + err);
                reject(err);
            }
            resolve(result)
        })
    })
}

function get_food(type, room_id){
    // expects a type [vegetable | fruit] and room
    return new Promise((resolve, reject) => {
        sql = "select name, qty from ? where room_id = ?";
        db_connection.query(sql, [type, room_id], function (err, result){
            if (err){
                console.log("An vegetable error has occurred: " + err);
                reject(err);
            }
            resolve(result);
        });
    })
}

现在你所有的异步东西都很简单。在异步函数中,您可以调用类似:

let items = await check_growth_items(socket.room)

或获取食物:

fruit[socket.room] = await get_food('fruit',socket.room )

get_food('fruit',socket.room )
.then(result => fruit[socket.room] = result)
.catch(err => console.log(err))

我承认不是100%确定你的最终代码应该做什么,但你的主要功能应该是:

async function starter (){
    // it's not clear in your code how you're using this
    // of it the other async calls depend on the return value
    var growth_items = await check_growth_items(socket.room)
    if (!vegetables[socket.room]) {
        vegetables[socket.room] = await get_food('vegetables',socket.room )
    }
    if (!fruit[socket.room]) {
        fruit[socket.room] = await get_food('fruit',socket.room )
    }

    console.log(vegetables[socket.room]);
    console.log(fruit[socket.room]);
} 

这可能不会成为一个切入点。粘贴解决方案,但希望能给你一些关于组织这些部分的更好方法的想法。

答案 1 :(得分:4)

您可以使用promisifycallback转换为promise,然后使用await

示例代码应该是这样的

const vegetables = {};
const fruit = {};
const Promise = require('bluebird'); // or you can use node utility module as well
const db = Promise.promisifyAll(require('YOUR DB LIB'));
const db_connection = 'YOUR DB CONNECTION'

async function starter (){
  const SQL = "select growth_items from garden where room_id = ?";
  try {
    const result = await db_connection.query(SQL);
    console.log(result);
    check_foods();
  } catch(err) {
    console.log("Garden Error: " + err);
  }
}

async function check_foods(){
  //Check to see if vegetables[socket.room] already exists, otherwise load it from the database
  if (typeof vegetables[socket.room] !== "undefined"){
    const SQL = "select name, qty from vegetables where room_id = ?";
    try {
      const result = await db_connection.query(SQL);
      vegetables[socket.room] = result;
    } catch(err) {
      console.log("An vegetable error has occurred: " + err);
      return;
    }
  }

  //Check to see if fruit already exists before looking up again
  if (typeof fruit[socket.room] !== "undefined"){
      const SQL = "select name, qty from fruit where room_id = ?";
      try {
        const result = await db_connection.query(SQL);
        fruit[socket.room] = result;
      } catch(err) {
        console.log("An fruit error has occurred: " + err);
        return;
      }
  };
}