我遇到了一个问题,我希望在继续之前等待异步数据库查询及其操作。
我当然可以将操作放在金字塔中,但从长远来看它不会很酷,因为我必须在某些时候重复代码。
这是我的例子(由于数据库查询的异步,当然不能正常工作):
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,但我目前无法理解。
对代码的任何其他建议都非常受欢迎 感谢。
答案 0 :(得分:0)
我在评论中已经解释过使用Promise
s。我假设您正在为您的NodeJS程序使用mysql
库。
首先,为了避免金字塔(或者我们通常称之为回调地狱),我们可以尝试将异步函数包装成Promise
,如下所示:
function queryPromise(str, params) {
return new Promise((resolve, reject) => {
dbconn.query(str, params, (err, result, fields) => {
if (err) reject(err);
resolve(result);
})
})
}
然后,我只宣传了重要部分:
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()
链接到其他查询中,并避免更多地缩进代码,这会导致创建回调地狱。虽然,这不是我喜欢做的事情,因为当我们不小心它时,Promise链接也会带来地狱。
如果您使用的是Node 8或更高版本,则使用async await
是最佳解决方案。考虑到async await
也使用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 = "";
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感到满意时(甚至更好,与async-await一起使用),它会使用Promises
我希望这会有所帮助。祝你好运!