Ожидание завершения запроса к базе данных mysql перед продолжением

У меня проблема, когда я хочу дождаться асинхронного запроса к базе данных и его операций, прежде чем продолжить.

Я, конечно, мог бы поместить операции внутри пирамиды, но в долгосрочной перспективе это не будет круто, потому что мне иногда придется дублировать код.

Вот мой пример (который, конечно, сейчас не будет работать из-за асинхронности запросов к базе данных):

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. Это может позволить вам избежать ада пирамиды обратных вызовов при решении вашей проблемы. Вы можете попробовать обернуть функцию запроса в обещания.

ionizer 11.03.2018 13:41

@ionizer Не могли бы вы показать мне пример того, как бы вы обернули функции запроса? Всего лишь по одной функции запроса, и я буду очень признателен.

TheE 11.03.2018 14:08

Вы можете попробовать такой код: function q(str, params) { return new Promise((resolve, reject) => {dbconn.query(str, params, (err, result, fields) => {if (err) reject(err); resolve(result)})})}. Я придумал ответ, используя это, если вы не против подождать еще немного.

ionizer 11.03.2018 14:14

@ionizer Да, конечно, если хочешь, я могу дождаться ответа, но я думаю, что знаю, что ты имеешь в виду, и смогу заставить его работать, но все же я буду ждать аккуратной версии. :)

TheE 11.03.2018 14:19

Я опубликовал ответ, вы можете выбрать любой подход. Кстати, какую версию Node вы используете?

ionizer 11.03.2018 15:14
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
5
2 071
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Я объяснил в комментариях об использовании Promise. И я предполагаю, что вы используете библиотеку mysql для своей программы NodeJS.

Итак, во-первых, чтобы избежать пирамиды (или ада обратных вызовов, как мы ее обычно называем), мы можем попробовать обернуть функцию async в 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() с другими запросами внутри и избежать еще большего отступа вашего кода, что приведет к созданию ада обратных вызовов. Хотя это не то, что мне нравится делать, поскольку цепочка обещаний также приносит ад, когда мы не будем осторожны с этим.

Если вы используете Node 8 или выше, использование async await - лучшее решение. Учитывая, что async await также использует обещания, мы можем сделать это так:

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).

Надеюсь, это поможет. Удачи!

Один вопрос, если я поставлю, скажем, «myfunc ()» как async, тогда как мне дождаться его обратного вызова, потому что я делаю так: var squareweb = myfunc(); И позже, используя переменную squareweb, поэтому myfunc () не может быть асинхронным . Придется ли мне создавать еще одно обещание для myfunc () или?

TheE 11.03.2018 15:42

Функции async возвращают обещание, и все, что вы return внутри них, совпадает с resolve()-обещанием с данными. Таким образом, вы можете использовать squareweb.then() или даже снова использовать await. Для чего нужен var squareweb и как он будет использоваться?

ionizer 11.03.2018 15:54
somefunc(req).then(function(gweb) { squareweb = gweb; /*Some other code*/ } Готово. Большое спасибо :)
TheE 11.03.2018 16:07

Другие вопросы по теме