我遇到一个问题,我想等待异步数据库查询及其操作,然后再继续。
我当然可以将操作放在金字塔内,但从长远来看这并不酷,因为有时我必须重复代码。
这是我的示例(由于数据库查询异步,当前当然无法工作):
var level = 5;
var difficulty = 30; //example
let randomDecider = Math.floor(Math.random()*(50+level)+1);
if (difficulty < randomDecider) {
var type;
var name;
var heroid = "";
dbconn.query("SELECT * FROM owned_heroes WHERE user = ? AND equipped = 1", [req.session.login], function(err, result, fields) {
heroid = result[0].heroid;
});
if (randomDecider > 50) {
type = "skill";
var ownedSkills = [];
var skillsKeys = Object.keys(Skill);
dbconn.query("SELECT * FROM owned_skills WHERE user = ? AND heroid = ? AND equipped = 1", [req.session.login, heroid], function(err, result, fields) {
for (var i = 0; i < result.length; i++) {
ownedSkills.push(result[i].name);
}
});
//Here later I also want to remove ownedSkills from skillsKeys.
name = skillsKeys[Math.floor(Math.random()*skillsKeys.length)];
}
else {
type = "item";
var itemsKeys = Object.keys(Item);
var ownedItems = [];
dbconn.query("SELECT * FROM owned_items WHERE user = ? AND heroid = ? AND equipped = 1", [req.session.login, heroid], function(err, result, fields) {
for (var i = 0; i < result.length; i++) {
ownedItems.push(result[i].name);
}
});
//Here later I also want to remove ownedItems from itemsKeys.
name = itemsKeys[Math.floor(Math.random()*itemsKeys.length)];
}
//Some other code using the type and name variable.
那么有人可以根据这个解释我如何将其转换为有效的东西,比如等待查询后的操作完成然后再继续。 我尝试了 async/await,但目前无法弄清楚。
也非常欢迎对代码提出任何其他建议。
谢谢。
最佳答案
我已经在评论中解释了如何使用 Promise
s。我假设您正在使用 mysql
NodeJS 程序的库。
首先,为了避免金字塔(或者我们通常所说的回调 hell ),我们可以尝试将异步函数包装到 Promise
中。像这样:
function queryPromise(str, params) {
return new Promise((resolve, reject) => {
dbconn.query(str, params, (err, result, fields) => {
if (err) reject(err);
resolve(result);
})
})
}
那么,我只 promise 了重要的部分:
var level = 5;
var difficulty = 30; //example
let randomDecider = Math.floor(Math.random() * (50 + level) + 1);
if (difficulty < randomDecider) {
var type;
var name;
var heroid = "";
queryPromise("SELECT * FROM owned_heroes WHERE user = ? AND equipped = 1", [req.session.login]).then(result => {
heroid = result[0].heroid;
if (randomDecider > 50) {
........
您也可以使用此功能进行其他查询。可是等等!这不就等于放进金字塔了吗?嗯,它或多或少是相同的,并且通常是这样做的方法,以便您的代码按照我们想要的方式执行。但现在,我们可以链接 Promise 的 .then()
s 来自内部的其他查询,并避免进一步缩进代码,这会导致创建回调 hell 。不过,这不是我喜欢做的事情,因为当我们不小心处理时,Promise 链也会带来 hell 。
如果您使用的是 Node 8 或更高版本,请使用 async await
是最好的解决方案。考虑async await
也使用 Promises,我们可以这样做:
var level = 5;
var difficulty = 30; //example
let randomDecider = Math.floor(Math.random() * (50 + level) + 1);
if (difficulty < randomDecider) {
var type;
var name;
var heroid = "";
let heroidQuery = await queryPromise("SELECT * FROM owned_heroes WHERE user = ? AND equipped = 1", [req.session.login]);
heroid = heroidQuery[0].heroid;
if (randomDecider > 50) {
........
现在看起来好多了,不是吗?正如关键字所示,await
使您的代码等待从查询中检索结果。只是不要忘记将整个代码包装到 async function()
中。阻止为 await
不允许外出async
功能。
async function myfunc() {
var level 5;
....
我建议查看诸如mysql2/promise
之类的库甚至 sequelize
当您对 Promises 感到满意时,它会使用 Promises(或者更好的是,与 async-await 一起使用)
我希望这有帮助。祝你好运!
关于javascript - 等待 mysql 数据库查询完成后再继续,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49210653/