используя асинхронную функцию в цикл с nodejs? - PullRequest
1 голос
/ 27 июня 2019

Я должен проверить, существует ли foreignKey, но я не могу сделать цикл с моей функцией асинхронного запроса

function checkAllFK(tables, foreignKeys) {
  let index = -1;
  for (var key in foreignKeys) {
    index++;
    QueryFunction(tables[index], key, foreignKeys[key])
    .then(result => {
    if(result == null) {
      //here, if result is null, that's mean the foreignKey doesn't exist, then, we have to stop the loop and return false;
      return false;
    }
    else if(index == (tables.length - 1)) {
      //here, that's mean we are at the end of the loop, and we doesn't break it with the previous if, that's mean all foreignKey exist, then, we return true;
      return true;
    }
  }

проблема в том, что в конце первой итерации вы выходите из функции ирезультат возврата зависит только от первой итерации: false, если условие if выполнено на первой итерации, null, если нет

, даже если посмотреть здесь много похожих тем, я не нашел решения длямоя проблема.

Ответы [ 3 ]

2 голосов
/ 27 июня 2019

Ваша операция «проверить все foreignKeys против всех tables» может быть записана в одну строку.

function checkAllFK(tables, foreignKeys) {
  return Promise.all(tables.map(t => Promise.all(foreignKeys.map(k => QueryFunction(t, k))));
}

Эта функция возвращает обещание, которое разрешается после выполнения всех запросов, поэтому вы вызываете егокак

checkAllFK(tables, foreignKeys)
    .then(/* success */)
    .catch(/* error */);

Однако, в зависимости от количества foreignKeys и tables и сложности QueryFunction, это может создать огромную нагрузку на сервер базы данных.Если имеется 10 таблиц и 1000 внешних ключей, это попыталось бы выполнить 10000 запросов параллельно к серверу базы данных.Это не очень разумно.

SQL создан для решения этих ситуаций.Вместо того, чтобы выполнять 10000 запросов для одной вещи каждый, вы можете решить выполнить один запрос для 10000 вещей.Или 10 запросов на 1000 вещей каждый.Оба, очевидно, лучше, чем забивать сервер базы данных 10 000 запросов.

Например, это возвращает все внешние ключи, которые не существуют в table_1 за один шаг.

SELECT
  k.key_column
FROM
  foreign_keys k
  LEFT JOIN table_1 t ON t.key_column = k.key_column
WHERE
  t.key_column IS NULL

Зависит отна то, что вы делаете в своем QueryFunction, как должен выглядеть фактический SQL.

Тот факт, что у вас есть более одной таблицы для проверки одних и тех же внешних ключей, также вызывает беспокойство, это обычно является признакомплохой дизайн базы данных.

0 голосов
/ 27 июня 2019

вы можете сделать то же самое, как распечатать сообщение в консоли или записать в файл, можете получить визуальный результат.

Если вы хотите получить результат, пожалуйста, подождите.

0 голосов
/ 27 июня 2019

мало распространенных ошибок для начинающих. Давайте начнем с хитрого и используем ключевое слово var в цикле for в асинхронном контексте. Как видите, это вернет вам только 10 с, а не 1, 2, 3.

for (var i=0; i < 10; i++) {
  setTimeout(() => console.log(i), 100);
}

Исправить легко в этом случае - просто используйте let, который имеет область действия, отличную от var и работает так, как вы ожидаете.

    for (let i=0; i < 10; i++) {
      setTimeout(() => console.log(i), 100);
    }

Второй - это асинхронный контекст - цикл for заканчивается до того, как вы выполните асинхронный контекст внутри обещания, возвращаемого QueryFunction. Если вы можете использовать более новую версию Node.js, тогда async/await - ваш спаситель, просто пометьте вашу функцию как async и получите

const result = await QueryFunction(tables[index], key, foreignKeys[key])

Однако будьте осторожны - если у вас есть что-то в контексте Promise / Asynchronous, вы в основном не можете вернуться к синхронному контексту. Поэтому вся ваша логика должна знать, что вы находитесь в асинхронной части. Это в основном означает, что все результаты будут обещаниями, и вам нужно будет then их или await их. Это не ошибка или что-то в этом роде, и вы должны на это рассчитывать.

...