请问如何解决Nodejs中node-mysql多层回调的问题
请问如何解决Nodejs中node-mysql多层回调的问题
例如:
table_user: userId, userName
table_user_course: userId, courseName
现在我想通过node获得这样的结果:
[
{
"userID": 1,
"userName": "mark",
"userCourse": [
{
"courseName": "math"
},
...
]
},
...
]
我是准备这样解决的:
// require("mysql");
// mysql connection
var resData = null;
mysql.query({
sql: 'SELECT * FROM table_user'
}, function(err, rows) {
// if rows && rows.length>0
var usersInfo = [];
for (var row in rows) {
var userInfo = {
userId: row.userId,
userName: row.userName,
userCourse: []
};
mysql.query({
sql: 'SELECT * FROM table_course WHERE userID = '+row.userId
}, function(err, rows) {
/* 这里怎么把获取的信息返回给上面的userInfo.userCourse */
});
usersInfo.push(userInfo);
}
/* 这里怎么把最后的usersInfo赋值给resData */
resData = usersInfo;
});
/* 上面的有很多是伪代码,怕文字表述不清才这样写的,所以大家不要在意个别小错误=。= */
所以请问:
- 用
async
是可以解决单次依赖,那循环多次那块应该怎么办?可以继续用async
解决问题吗? - 有其他办法或途径可以解决吗?比如能否用
sql
语句直接解决问题==#
谢谢大家…
要解决Node.js中node-mysql
多层回调的问题,我们可以使用async/await
语法来简化异步操作,并且让代码更易读。此外,我们还可以优化SQL查询以减少数据库往返次数。以下是解决方案:
使用 async/await
首先,我们需要确保我们的MySQL库支持async/await
。如果你使用的是标准的mysql
库,你可能需要引入util.promisify
来将回调风格的API转换为Promise风格。
const mysql = require('mysql');
const util = require('util');
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'database_name'
});
const query = util.promisify(pool.query).bind(pool);
async function getUserCourses() {
try {
const users = await query('SELECT * FROM table_user');
const usersWithCourses = await Promise.all(users.map(async user => {
const courses = await query('SELECT * FROM table_user_course WHERE userId = ?', [user.userId]);
return {
userId: user.userId,
userName: user.userName,
userCourse: courses.map(course => ({
courseName: course.courseName
}))
};
}));
console.log(usersWithCourses);
return usersWithCourses;
} catch (error) {
console.error(error);
}
}
getUserCourses();
使用联合查询(JOIN)
为了减少数据库往返次数,你可以考虑使用SQL中的JOIN来一次性获取所有数据。这可以通过在SQL查询中使用JOIN
来实现。
SELECT u.userId, u.userName, c.courseName
FROM table_user u
LEFT JOIN table_user_course c ON u.userId = c.userId;
然后在Node.js中处理结果:
async function getUserCourses() {
try {
const results = await query(`
SELECT u.userId, u.userName, c.courseName
FROM table_user u
LEFT JOIN table_user_course c ON u.userId = c.userId
`);
const groupedResults = results.reduce((acc, current) => {
const existingUser = acc.find(user => user.userId === current.userId);
if (existingUser) {
existingUser.userCourse.push({ courseName: current.courseName });
} else {
acc.push({
userId: current.userId,
userName: current.userName,
userCourse: [{ courseName: current.courseName }]
});
}
return acc;
}, []);
console.log(groupedResults);
return groupedResults;
} catch (error) {
console.error(error);
}
}
这两种方法都可以有效地解决多层回调的问题,并提高代码的可读性和性能。选择哪种方法取决于你的具体需求和数据库设计。
select a.userId, a.userName, b.courseName from table_user a join table_user_course b on a.userId=b.userId;
楼主好好补补 SQL。。。。
async 有很多方法啊…应该有可以解决的…
恩,谢谢,确实没怎么仔细研究过join
,这样确实可以在第一次执行sql的时候获取到所有想要的信息。那如果某个场景下需要执行两次sql,并且第二次依赖于第一次的结果应该怎样处理呢?
要解决Node.js中node-mysql
多层回调的问题,可以使用async/await
来简化异步代码,并且避免回调地狱(callback hell)。以下是两种解决方案:一种使用async/await
,另一种使用SQL联接。
使用async/await
首先需要安装mysql
和async
库:
npm install mysql async
然后你可以使用以下代码来解决这个问题:
const mysql = require('mysql');
const async = require('async');
const connection = mysql.createConnection({
host: 'localhost',
user: 'your_username',
password: 'your_password',
database: 'your_database'
});
connection.connect();
async function getUsersWithCourses() {
const [rows] = await new Promise((resolve, reject) => {
connection.query('SELECT * FROM table_user', (err, rows) => {
if (err) return reject(err);
resolve(rows);
});
});
const usersInfo = await Promise.all(rows.map(async (row) => {
const [courses] = await new Promise((resolve, reject) => {
connection.query('SELECT * FROM table_user_course WHERE userId = ?', [row.userId], (err, rows) => {
if (err) return reject(err);
resolve(rows);
});
});
return {
userId: row.userId,
userName: row.userName,
userCourse: courses.map(course => ({
courseName: course.courseName
}))
};
}));
console.log(usersInfo);
}
getUsersWithCourses().catch(console.error);
connection.end();
使用SQL联接
另一种解决方案是通过一次查询完成所有操作,使用SQL联接将两个表的数据合并到一个查询结果中。这可以通过以下SQL语句实现:
SELECT u.userId, u.userName, c.courseName
FROM table_user u
LEFT JOIN table_user_course c ON u.userId = c.userId
ORDER BY u.userId;
然后在Node.js代码中执行此查询:
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'your_username',
password: 'your_password',
database: 'your_database'
});
connection.connect();
connection.query(`
SELECT u.userId, u.userName, c.courseName
FROM table_user u
LEFT JOIN table_user_course c ON u.userId = c.userId
ORDER BY u.userId;
`, (err, rows) => {
if (err) throw err;
const usersInfo = {};
rows.forEach(row => {
if (!usersInfo[row.userId]) {
usersInfo[row.userId] = {
userId: row.userId,
userName: row.userName,
userCourse: []
};
}
if (row.courseName) {
usersInfo[row.userId].userCourse.push({ courseName: row.courseName });
}
});
console.log(Object.values(usersInfo));
});
connection.end();
以上两种方法都可以有效解决多层回调的问题。选择哪种方法取决于你的具体需求和数据库设计。