проблемы с асинхронной записью данных - PullRequest
0 голосов

есть код функции:

function fillingDataInCategory(categories, url) {
  let categoriesData = [];
  for (let i = 0; i < categories.length; i++) {
    conn.query(`SELECT product_id
                FROM products
                WHERE product_category_id = ${categories[i].id}`, (err, productInCategory) => {
      if(err) {
        console.log(err);
        fs.writeFileSync('api-reports-error-log.txt', 
          `${fs.readFileSync('api-reports-error-log.txt')}\n${url}: ${err} ${new Date().toLocaleDateString()}`);
      } else {
        console.log(productInCategory);
        categoriesData.push({category: categories[i].id, productInCategory: productInCategory.length});
      }
    });
  }
}

Проблема в том, что возвращается пустой массив categoryData из-за асинхронной записи. Я мало работал с асинхронностью, поэтому буду рад любой помощи.

1 Ответ

0 голосов
/ 01 июня 2020

Я не вижу возврата в конце вашей функции, но предполагаю, что вы хотите вернуть categoryData

Я думаю, что вы сейчас вызываете свою функцию следующим образом:

  function myFunc() {
    // Do stuff
    let categoriesData = fillingDataInCategory(categories, "myurl");
    console.log(categoriesData);
    // Do stuff
  }

Прежде всего, я советую вам использовать forEach вместо for ();

Я предлагаю вам использовать промис. И поскольку вы выполняете несколько запросов в одной функции, используйте Promise.all

Если библиотека, которую вы используете для выполнения вызовов mysql, позволяет это, используйте обещания напрямую, но если она позволяет выполнять только обратные вызовы, конвертируйте этот обратный вызов для обещания вроде этого:


function makeRequest(categorie) {
    return new Promise((resolve, reject) => {
       conn.query(`SELECT product_id FROM products WHERE product_category_id = ${categorie.id}`, (err, productInCategory) => {
            if (err) {
                reject(err) //reject at error
            } else {
                resolve({category: categorie.id, productInCategory: productInCategory /* You can put your .length here */}); //resolve with your result
            }
       });
    });
}

Вот код, который я написал для вас. Я имитирую ваш вызов do conn.query () с задержкой в ​​1 сек c

const fs = require('fs');

/* SIMULATE conn.query async call */

let conn = {
    query: (text, callback) => {
        setTimeout(callback(null, [1, 2, 3, 4] /* Return an fake array of result of length 4 */), 1000);
    }
}


function makeRequest(categorie) {
    return new Promise((resolve, reject) => {
       conn.query(`SELECT product_id FROM products WHERE product_category_id = ${categorie.id}`, (err, productInCategory) => {
            if (err) {
                reject(err) //reject at error
            } else {
                resolve({category: categorie.id, productInCategory: productInCategory.length}); //resolve with your result
            }
       });
    });
}

function fillingDataInCategory(categories, url) {
    return new Promise((resolve, reject) => {
        let promiseList = [] //Make a array to fill with pending promise
        categories.forEach((categorie) => {
            promiseList.push(makeRequest(categorie)); // Adding a new pending request with the categorie inside the array
        })
        resolve(Promise.all(promiseList)); // Promise.all return a promise that take a list of pending promise
    });
}

function myFunc() {
    fillingDataInCategory([{id: 1}, {id: 2}, {id: 3}], "myurl").then((categorieData) => {
        console.log(categorieData); //Now you get the resolve of the Promise.all
        //Do your post work
    }).catch((err) => { // If one of all the requests of the Promise.all array throw an error, then all requests fails
        //Do error stuffs
    });
    // Do stuff
}

myFunc();

и получаю следующее:

➜  node test-stackoverflow.js
[
  { category: 1, productInCategory: 4 },
  { category: 2, productInCategory: 4 },
  { category: 3, productInCategory: 4 }
]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...