我想对另一个查询的每一行执行一个sql查询,所以我写了一个函数
export function getLocations(req, res) {
let appData = [];
const database = new Database();
database.query('select * from districts')
.then(rows => {
rows.forEach(row => {
const new_database = new Database();
new_database.query(`SELECT locations.id,locations.name
FROM locations
.....
WHERE locations.district=?`, row.id)
.then(sub_rows => {
let district = row;
district["locations"] = sub_rows;
appData.push(district);
new_database.close();
}, err => {
return new_database.close().then(() => { throw err; })
})
.catch(err => {
console.log(err);
res.status(500).json("Database Error");
})
}, err => {
return database.close().then(() => { throw err; })
}).then(result => {
//final result
res.status(200).json(appData);
database.close()
})
.catch(err => {
console.log(err);
res.status(500).json("Database Error");
})
}
我的数据库类是
const mysql = require('mysql');
class Database {
constructor() {
this.connection = mysql.createConnection({
host: process.env.DB_HOST,
user: process.env.DB_USERNAME,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
port: 3306,
debug: false,
multipleStatements: false
});
}
query(sql, args) {
return new Promise((resolve, reject) => {
this.connection.query(sql, args, (err, rows) => {
if (err)
return reject(err);
resolve(rows);
});
});
}
close() {
return new Promise((resolve, reject) => {
this.connection.end(err => {
if (err)
return reject(err);
resolve();
});
});
}
}
module.exports = Database;
但是,这将继续执行并打印最终结果(空数组),而无需等待执行子查询。我尝试在行和 new_database.query 上进行异步等待,但是它仍然不等待子查询执行完成。我在这里可以做什么?
答案 0 :(得分:1)
我已经改善了您对sub-queries
的逻辑,并使用Promise.all()重新编写了它们:
export function getLocations(req, res) {
let appData = [];
const database = new Database();
database.query('select * from districts')
.then(rows => {
// create promise list for all sub-queries
const promise_list = rows.map(row => new Promise((resolve, reject) => {
const new_database = new Database();
return new_database.query(`SELECT locations.id,locations.name FROM locations .... WHERE locations.district=?`, row.id)
.then(sub_rows => {
let district = row;
district["locations"] = sub_rows;
appData.push(district);
new_database.close();
resolve(district);
}, err => {
return new_database.close().then(() => { throw err; })
});
})
);
// execute all sub-queries in parallel and wait for them
Promise.all(promise_list).then(result => {
res.status(200).json(appData);
database.close()
}).catch(err => {
console.log(err);
res.status(500).json("Database Error");
});
});
}
PS:您可以将appData
声明为const
,只是将数据推入其中。不重新分配它。
答案 1 :(得分:0)
使用JOIN尝试获得想要的结果。可用的功能取决于MySQL版本,因此您可能需要GROUP_CONCAT而不是JSON_ARRAYAGG
SELECT districts.*, JSON_ARRAYAGG(locations)
FROM districts
LEFT JOIN locations
ON locations.district=districts.id
GROUP BY districts.id
JavaScript联接的性能令人震惊,因此让数据库执行其设计的工作。