如何使用嵌套的HTTP请求更新字典?

时间:2019-11-29 14:31:22

标签: javascript node.js asynchronous promise axios

我将尽我所能清楚地解释这一点,但这让我很困惑,所以请耐心等待。

对于这个项目,我将Node.js与Axios和Cheerio模块结合使用。

我正在尝试从网上商店(类似于Amazon / eBay)获取HTML数据,并将产品信息存储在字典中。我设法存储了大多数东西(标题,价格,图像),但是产品说明在另一个页面上。要对此页面进行请求,我使用的是从第一个请求中获得的URL,因此它们是嵌套的。

第一部分是通过以下请求完成的:

let request = axios.get(url)
  .then(res => {
    // This gets the HTML for every product
    getProducts(res.data);
    console.log("Got products in HTML");
  })
  .then(res => {
    // This parses the product HTML into a dictionary of product items
    parseProducts(productsHTML);
    console.log("Generated dictionary with all the products");
  })
  .then(res => {
    // This loops through the products to fetch and add the description
    updateProducts(products);
  })
  .catch(e => {
    console.log(e);
  })

我还将提供创建产品对象的方式,因为这可能会澄清我认为出现问题的功能。

function parseProducts(html) {
  for (item in productsHTML) {
    // Store the data from the first request
    const $ = cheerio.load(productsHTML[item]);
    let product = {};
    let mpUrl = $("a").attr("href");
    product["title"] = $("a").attr("title");
    product["mpUrl"] = mpUrl;
    product["imgUrl"] = $("img").attr("src");
    let priceText = $("span.subtext").text().split("\xa0")[1].replace(",", ".");
    product["price"] = parseFloat(priceText);

    products.push(product);
  }
}

问题出在updateProducts函数中。如果以后我用console.log字典,则不添加描述。我认为这是因为控制台将在添加描述之前记录日志。这是更新功能:

function updateProducts(prodDict) {
  for (i in prodDict) {
    let request2 = axios.get(prodDict[i]["mpUrl"])
      .then(res => {
        const $ = cheerio.load(res.data);
        description = $("div.description p").text();
        prodDict[i]["descr"] = description;
        // If I console.log the product here, the description is included
      })
  }
// If I console.log the product here, the description is NOT included
}

我不知道要尝试什么,我想可以通过async / await之类的方法或在代码上设置超时来解决。有人可以帮助我正确更新产品并添加产品说明吗?提前非常感谢您。

1 个答案:

答案 0 :(得分:1)

要使用async / await重构它,可以这样做:

async function fetchAndUpdateProducts() => {
  try {
    const response = await axios.get(url);

    getProducts(response.data);
    console.log("Got products in HTML");

    parseProducts(productsHTML);
    console.log("Generated dictionary with all the products");

    await updateProducts(products);
  } catch(e) {
    console.log(e);
  }
}

fetchAndUpdateProducts().then(() => console.log('Done'));

async function updateProducts(prodDict) {
  for (i in prodDict) {
    const response = await axios.get(prodDict[i]["mpUrl"]);
    const $ = cheerio.load(response.data);
    description = $("div.description p").text();
    prodDict[i]["descr"] = description;
  }
}

除非已解决updateProducts返回的承诺,否则不会继续结束对fetchAndUpdateProducts的调用。