Использование forEach для создания другого массива с помощью метода push, но после завершения цикла массив пуст

Мне нужна помощь, чтобы понять причину, по которой после forEach моя константа становится пустой. Я читаю и нахожу несколько вопросов, но ни один из них не помогает мне понять. Я считаю, что это происходит потому, что JS асинхронен, но я не могу понять, как решить эту проблему.

Итак, код очень прост. У меня есть API NodeJS, который подключается к нескольким базам данных и возвращает всю информацию. Я использую pg-prom для подключения к PostgreSQL.

export default class AllInfo {
  constructor(databases) {
    this.databases = databases;
    this.options = {
      promiseLib: promise,
    };
    this.databaseConnection = new Pg(this.options);
  }

И после этого метод трюка:

 getAllInformation() {
    const entidades = [];
    this.databases.getStringConnection().forEach((db) => {
      const connection = this.databaseConnection(db);
      connection.any('SELECT * FROM information').then((data) => {
        entidades.push(data);
      });
      connection.$pool.end();
    });
    return entidades;
  } 

В этом коде мой возврат всегда пустой ([]), когда его запрашивают.

Если я регистрирую константы внутри цикла, информация регистрируется успешно. Но если я войду после цикла и до возврата, он будет пустым.

 getAllInformation() {
    const entidades = [];
    this.databases.getStringConnection().forEach((db) => {
      const connection = this.databaseConnection(db);
      connection.any('SELECT * FROM information').then((data) => {
        entidades.push(data);
        console.info(entidades) // here it works
      });
      connection.$pool.end();
    });
    return entidades;
  } 

И если я попытаюсь выйти наружу:

 getAllInformation() {
    const entidades = [];
    this.databases.getStringConnection().forEach((db) => {
      const connection = this.databaseConnection(db);
      connection.any('SELECT * FROM information').then((data) => {
        entidades.push(data);

      });
      connection.$pool.end();
    });
    console.info(entidades) // here doesn't work
    return entidades;
  }

Кто-нибудь может объяснить, почему это происходит и где я ищу решение?

Я также думаю, что это асинхронная проблема, попробуйте использовать обещание или async / await

Chris Li 13.09.2018 17:53

Зачем вам const? Следует ли менять const? Может, хочешь var?

Bunyk 13.09.2018 17:53

«Использование forEach для создания другого массива с помощью метода push…» в любом случае полностью неверен. Для этого был создан .map.

Bergi 13.09.2018 18:08

Поскольку вы уже используете обещания, взгляните на Promise.all.

Bergi 13.09.2018 18:10

@Bunyk const не меняет свой ценить, но для объектов (а массив является объектом) это означает переназначение объекту другой. Например, const myObj = {name: "alice" };, за которым следует myObj = {name: "bob"}. Однако myObj.name = "bob" действителен. Кроме того, если вам не нужен const, то лучше использовать let, а не var. Есть очень мало причин, по которым вам нужен var, если вы можете просто использовать ключевые слова ES6.

VLAZ 13.09.2018 18:23

@Bunyk дополняет объяснение vlaz, если я объявляю let, Lint выдает мне: «'entidades' никогда не переназначается. Вместо этого используйте 'const'. (Prefer-const)».

Francisco 13.09.2018 18:43

@vlaz Раньше я не встречал этого вопроса. Возможно, это потому, что упоминается Ajax. Спасибо, что там хорошая информация.

Francisco 13.09.2018 18:47

Кроме того, инициализация соединения и последующее уничтожение пула соединений внутри метода выглядят очень неправильно. Это не то, как вы используете pg-promise. См .: Где инициализировать pg-prom.

vitaly-t 15.09.2018 06:35

Привет, @ vitaly-t, это большая честь. Я использую для подключения к нескольким базам данных и выполнения выбора. Поэтому, если я закрываю соединение, я получаю предупреждение в консоли. Также это соединение больше нигде не используется. Представьте себе многопользовательское приложение, в котором вы хотите выполнять запросы к разным базам данных. Я не знаю, как сохранить соединение открытым для следующего запроса, если я не знаю, какая база данных идет. Вы так использовали? Есть предположения?

Francisco 16.09.2018 16:49

@Francisco Simple - вы создаете по одному db для каждого соединения, а затем повторно используете их. И если у вас есть динамический список, должен быть уникальный ключ, который вы можете поместить в хэш, а затем при необходимости вытащить оттуда нужный объект db.

vitaly-t 16.09.2018 21:22

@ vitaly-t, спасибо, я сделаю это. Цените помощь.

Francisco 19.09.2018 21:52
Поведение ключевого слова "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
11
168
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

connection.any() возвращает обещание и выполняет анонимную функцию, которая помещает данные в ваш массив ПОСЛЕ выполнения обещания. Вот почему анонимная функция выполняется асинхронно. Однако вы можете подождать, пока данные будут возвращены функцией any, например:

let data = await connection.any('SELECT * FROM information');
entidades.push(data);

Учитывая, что OP все еще использует forEach, размещение await там не поможет - это эквивалентно вызову .then(), который они в настоящее время используют.

Bergi 13.09.2018 18:09

Привет, @Psycho, спасибо за попытку помочь. Если я изменю этот код, проект не будет компилироваться. Ошибка: «ожидание - зарезервированное слово».

Francisco 13.09.2018 18:49
Ответ принят как подходящий

Это так, как вы думаете. Он возвращает пустой массив, потому что JS является асинхронным, а вы возвращаете данные, как если бы они были синхронными.

Вы можете поместить обещания connection.any('SELECT * FROM information') в массив вместо того, чтобы помещать результат, таким образом, вы можете подождать, пока все обещания не будут разрешены / отклонены, чтобы продолжить.

попробуй это:

function getAllInformation() {
    const entidades = [];
    var entidadesPromises = [];
    this.databases.getStringConnection().forEach((db) => {
        const connection = this.databaseConnection(db);
        entidadesPromises.push(connection.any('SELECT * FROM information'));
        connection.$pool.end();
    });
    return Promise.all(entidadesPromises).then((data) => {
        entidades.push(data);
        console.info(entidades) // here it works
        return entidades;
    });
} 

getAllInformation().then(entidades => {
    // Entidades will be an array containing the data retrieved from the databases.
});

Большое тебе спасибо. Прекрасно работает. Теперь я понимаю. Я прочитаю больше о обещаниях и асинхронном режиме JS.

Francisco 13.09.2018 19:04

Я рад, что помог. Если позволите, дам хорошую книгу. Погуглите «вы не знаете js-обещаний».

Guy who types fast 13.09.2018 19:29

Я буду читать, я ценю совет. Спасибо.

Francisco 13.09.2018 20:08

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