Node.js - Как вернуть обратный вызов с массивом из цикла for с запросом MySQL? - PullRequest
1 голос
/ 22 апреля 2019

Я пытаюсь получить список виртуальных сообществ в моем приложении Node.js, а затем вернуть его с помощью функции обратного вызова. Когда я вызываю метод getList () с обратным вызовом, он возвращает пустой массив.

const mysqli = require("../mysqli/connect");

class Communities{

  getList(callback){
    var list = [];

    mysqli.query("SELECT * FROM communities", (err, communities) => {

      for(let i = 0; i < communities.length; i++){
        mysqli.query("SELECT name FROM users WHERE id='"+ communities[i].host +"'", (err, host) => {

          list.push({
            "id": communities[i].id,
            "name": communities[i].name,
            "hostID": communities[i].host,
            "hostName": host[0].name,
            "verified": communities[i].verified,
            "people": communities[i].people
          });

        });
      }

      callback(list);
    });
  }

}

new Communities().getList((list) => {
  console.log(list);
});

Мне нужно сделать цикл for асинхронным и вызвать обратный вызов, когда цикл for заканчивается. Пожалуйста, дайте мне знать, как это сделать. Спасибо.

1 Ответ

2 голосов
/ 22 апреля 2019

Обратные вызовы становятся действительно уродливыми, если вам нужно объединить несколько из них, поэтому Promises были изобретены, чтобы упростить это.Чтобы использовать Promises в вашем случае, вы должны сначала создать Promise при запросе базы данных¹:

 const query = q => new Promise((resolve, reject) => mysqli.query(q, (err, result) => err ? reject(err) : resolve(result)));

Теперь выполнение нескольких запросов вернет несколько обещаний, которые можно объединить, используя Promise.all, в одно обещание²:

 async getList(){
   const communities = await query("SELECT * FROM communities");

   const result = await/*³*/ Promise.all(communities.map(async community => {
      const host = await query(`SELECT name FROM users WHERE id='${community.host}'`);/*⁴*/

       return {
        ...community,
        hostName: host[0].name,
       };
    }));

    return result;
  }

Теперь вы можете легко получить результат с помощью:

 new Communities().getList().then(list => {
   console.log(list);
 });

Читать дальше:

Работа с обещаниями - Разработчики Google

Понимание async / await - Ponyfoo

Примечания:

¹: если вы делаете это чаще, вам, вероятно, лучше использовать библиотеку mysql, которая поддерживает обещанияизначально это экономит много работы.

²: благодаря этому запросы выполняются параллельно , что означает, что это намного быстрее, чем выполнять один за другим (что может быть сделаноиспользуя цикл for и ожидая внутри него).

³: await лишнее, но я предпочитаю оставить его для пометки как асинхронного действия.

⁴: я полагаюэто также можно сделать с помощью одного запроса SQL, такесли он слишком медленный для вашего варианта использования (в чем я сомневаюсь), вам следует оптимизировать сам запрос.

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