我正在尝试获取我的Node.js应用程序上的虚拟社区列表,然后使用回调函数返回它。当我使用回调调用getList()方法时,它返回一个空数组。
const mysqli = require("../mysqli/connect");
class Communities{
getList(callback){
var list = [];
mysqli.query("SELECT * FROM communities", (err, communities) => {
for(let i = 0; i < communities.length; i++){
mysqli.query("SELECT name FROM users WHERE id='"+ communities[i].host +"'", (err, host) => {
list.push({
"id": communities[i].id,
"name": communities[i].name,
"hostID": communities[i].host,
"hostName": host[0].name,
"verified": communities[i].verified,
"people": communities[i].people
});
});
}
callback(list);
});
}
}
new Communities().getList((list) => {
console.log(list);
});
我需要使循环到异步并在for循环结束时调用回调。请让我知道如何做到这一点。谢谢。
如果你必须将它们中的多个组合在一起,回调会变得非常难看,这就是为什么Promises被发明来简化它。要在你的情况下使用Promise,你必须在查询数据库时首先创建一个Promise:
const query = q => new Promise((resolve, reject) => mysqli.query(q, (err, result) => err ? reject(err) : resolve(result)));
现在做多个查询将返回多个promise,可以使用Promise.all
组合到一个promise²:
async getList(){
const communities = await query("SELECT * FROM communities");
const result = await/*³*/ Promise.all(communities.map(async community => {
const host = await query(`SELECT name FROM users WHERE id='${community.host}'`);/*⁴*/
return {
...community,
hostName: host[0].name,
};
}));
return result;
}
现在您可以轻松获得结果:
new Communities().getList().then(list => {
console.log(list);
});
继续阅读:
Working with Promises - Google Developers
Understanding async / await - Ponyfoo
笔记:
¹:如果你经常这样做,你可能应该使用一个本机支持promises的mysql库,这可以保证很多工作。
²:通过这些请求是并行完成的,这意味着它比一个接一个地做得更快(可以使用for循环并在其中等待)。
³:那个await
是多余的,但我更愿意将它标记为异步动作。
⁴:我想这也可以使用一个SQL查询来完成,所以如果它对你的用例来说太慢了(我怀疑)你应该优化查询本身。