【问题标题】:problems with asynchronous data recording异步数据记录的问题
【发布时间】:2020-05-25 21:36:24
【问题描述】:

有一个功能码:

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});
      }
    });
  }
}

问题是由于异步写入,返回了一个空的categoriesData数组。 我在异步方面的工作不多,所以我很乐意得到任何帮助。

【问题讨论】:

  • 您需要:1. 向fillingDataInCategory 添加一个“回调”参数,2. 返回一个承诺或 3. 使用 async/await
  • 能否给我一个代码示例,因为我不完全理解你?

标签: javascript mysql node.js express


【解决方案1】:

我没有在你的函数末尾看到返回,但我假设你想返回 categoryData

我认为您目前正在这样调用您的函数:

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

首先,我建议你使用 forEach 而不是 for();

我建议你使用一个承诺。当您在一个函数中执行多个查询时,请使用 Promise.all

如果你用来进行 mysql 调用的库允许它,请直接使用 Promise,但如果它只允许你进行回调,则将该回调转换为这样的 Promise:


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
            }
       });
    });
}

这是我为您编写的代码。我模拟你的通话做 conn.query() 延迟 1 秒

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 }
]

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2013-07-19
    • 2015-10-18
    • 2017-06-05
    • 2015-06-20
    • 1970-01-01
    • 2013-06-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多