![](/img/trans.png)
[英]Node.js Promises in nested callbacks in Promises in Promises not resolving
[英]Promises resolving to undefined with node.js mysql queries
我正在编写一条从表单中获取用户输入数据并使用该数据在我的数据库上执行一些单独查询的路由。 这一切都经过充分测试,我知道我可以获取用户输入、查询数据库并返回结果。 然而,给我带来麻烦的部分是我想从所有返回的数据中随机 select 一些结果,所以我将结果推送到一个大数组中。 但是由于查询是异步执行的,访问数据的唯一方法是在回调中,当然,如果我尝试在回调中推送行,我仍然无法在回调函数之外访问该数组,因为该代码将执行在查询甚至运行之前。 所以我尝试使用 JavaScript async/await 语法来执行查询,如下所示:
module.exports = {
search: (req, res) => {
function saveResults(resultsObj) {
Object.keys(resultsObj).forEach(function (key) {
var row = resultsObj[key];
var song = row.song_name
resultsArray.push(song);
return resultsArray;
});
}
async function queryForSong(){
var songGenre;
getSongGenre = "The queries aren't important, I know they work as expected";
await mysqlConnection.query(getSongGenre, (err, rows) => {
if (err) throw err;
songGenre = row[0].song_genre;
songSearchQuery = "SELECT query";
mysqlConnection.query(songSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
});
}
async function queryForArtist() {
var artistID;
getArtistID = "SELECT query";
await mysqlConnection.query(getArtistID, (err, rows) => {
if (err) throw err;
artistID = rows[0].artist_id;
console.log(rows, artistID);
artistSearchQuery = "SELECT query";
mysqlConnection.query(artistSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
});
}
async function queryForGenre() {
genreSearchQuery = "SELECT query";
await mysqlConnection.query(genreSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
}
async function queryForDecade() {
decadeSearchQuery = "SELECT query";
await mysqlConnection.query(decadeSearchQuery, (err, rows) => {
if (err) throw err;
return saveResults(rows);
});
}
var resultsArray = [];
var artist = req.body.searchArtist;
var song = req.body.searchSong;
var genre = req.body.searchGenre;
var decade = req.body.searchDecade;
if (song) {
queryForSong().then((value) => console.log(value)); //these all log undefined
}
if (artist) {
queryForArtist().then((value) => console.log(value));
}
if (genre) {
queryForGenre().then((value) => console.log(value));
}
if (decade) {
queryForDecade().then((value) => console.log(value));
}
}
}
然后的想法是将promise中已解决的行保存到一个大数组中并从那里随机化。 我唯一想到为什么这不起作用是因为返回语句位于回调函数内部? 正如这篇文章所解释的那样,我还直接使用 Promise 尝试了它,而是像这样编写我的所有异步函数:
function queryForGenre() {
genreSearchQuery = "SELECT query";
return new Promise(function (resolve, reject) {
mysqlConnection.query(genreSearchQuery, (err, rows) => {
if (err) reject(err);
resolve(saveResults(rows));
});
});
}
但无论哪种方式,.then 中的 console.log 语句仍然打印未定义,这意味着我的承诺没有解析为我给它的 saveResults(rows) 值。 我是否也需要使 saveResults function 异步? 根据我对承诺的理解,这似乎应该有效。 我错过了什么? 或者有没有更简单的方法来做到这一点?
您的函数queryForSong
、 queryForDecade
等正在使用await
,但 mysql 驱动程序查询 function 接受回调并且不返回 promise。 此外,回调内部的返回范围是回调范围内的,而不是外部异步 function 的范围。 而是将 function 包装在 promise 中,在必要时解决并拒绝。 除非绝对必要,否则还要避免使用 await,因为使用它会阻塞事件循环。 我已经给出了一个示例,说明如何使用 promise 包装queryForSong
function queryForSong(){
return new Promise((resolve, reject) => {
let songGenre;
const getSongGenre = "The queries aren't important, I know they work as expected";
mysqlConnection.query(getSongGenre, (err, rows) => {
if (err) reject(err);
else {
songGenre = row[0].song_genre;
const songSearchQuery = "SELECT query";
mysqlConnection.query(songSearchQuery, (err, rows) => {
if (err) reject(err);
else
resolve(saveResults(rows));
});
}
});
});
}
所以事实证明是 saveResults function 引起了我的问题。 我不完全理解为什么这会解决它,但我没有解决 saveResults function 的值,而是尝试在每个 function 中包含 saveResults 主体,返回 ZB321DE3BDC299EC807E9F7 和 5DDDE 有效。 例如,
function queryForSong() {
var songResultsArray = [];
var songGenre;
getSongGenre = "SELECT query";
return new Promise(function (resolve, reject) {
mysqlConnection.query(getSongGenre, (err, rows) => {
if (err) reject(err);
var row = rows[0];
songGenre = row.song_genre;
songSearchQuery = "SELECT query #2";
mysqlConnection.query(songSearchQuery, (err, rows) => {
if (err) throw err;
//this is the body of the saveResults function
Object.keys(rows).forEach(function (key) {
var row = rows[key];
var song = row.song_name;
songResultsArray.push(song);
});
resolve(songResultsArray);
});
});
});
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.