我试图找出异步调用函数的正确方法,如果它也在对数据库进行异步调用。
在我的代码中,我调用一个名为' 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;
});
};
}
答案 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)
您可以使用promisify
将callback
转换为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;
}
};
}