正确的异步/等待功能

时间:2020-10-20 04:21:27

标签: node.js

我正在尝试运行一个机器人,该机器人将某些产品(使用ASIN阵列)刮擦到Amazon(使用Amazon-buddy)并检查价格。如果价格不为0,则应该发送不一致的消息。我目前已将此设置每30秒运行一次,并且可以正常运行,但是有时似乎每个元素都没有等待forEach循环中的上一个元素获得响应,而我的函数似乎并不正确(我仍在尝试正确地了解异步/等待功能)。

是否有更好的方法来运行此操作,以便每个元素都等待刮擦前一个元素,然后再转到下一个元素,然后在30秒后再次运行循环?

(function() {
  var c = 0;
  var timeout = setInterval(function() {
      const checkStock = (async () => {
        config.items.itemGroup.forEach(element => {
          console.log('Checking stock on ' + element)
        try {
          const product_by_asin = await amazonScraper.asin({ asin: element });
          console.log(product_by_asin)
          const price = product_by_asin.result[0].price.current_price
          const symbol = product_by_asin.result[0].price.symbol
          const asin = product_by_asin.result[0].asin
          const title = product_by_asin.result[0].title
          const url = product_by_asin.result[0].url
          const image = product_by_asin.result[0].main_image

          if (price != 0) {
            const inStockResponse = {
              color: 0x008000,
              title: title + ' is in stock!',
              url: url,
              author: {
                name: config.botName,
                icon_url: config.botImg,
                url: config.botUrl
              },
              description: '<@767456705306165298>, click the tite to go purchase!\n\n' +
              'Price: ' + symbol + price,
              thumbnail: {
                url: image
              },
              timestamp: new Date()
              }
        
            message.channel.send({embed: inStockResponse });
            console.log(title + ' (' + asin + ') IS available!')
          } else {
            console.log(title + ' (' + asin + ') IS NOT available!')
          }
        } catch (error) {
          console.log(error);
        }
      });
      checkStock()
    });
    console.log('Counter: ' + c)
    c++;
  }, 30000);
})();

1 个答案:

答案 0 :(得分:1)

您可以使用for...of循环,该循环可以等待每次迭代完成:

async function checkItems(items) {
  // Check all items, wait for each to complete.
  for (const item of items) {
    try {
      const product_by_asin = await amazonScraper.asin({ asin: item });
      console.log(product_by_asin);
      const price = product_by_asin.result[0].price.current_price;
      const symbol = product_by_asin.result[0].price.symbol;
      const asin = product_by_asin.result[0].asin;
      const title = product_by_asin.result[0].title;
      const url = product_by_asin.result[0].url;
      const image = product_by_asin.result[0].main_image;

      if (price != 0) {
        const inStockResponse = {
          color: 0x008000,
          title: title + " is in stock!",
          url: url,
          author: {
            name: config.botName,
            icon_url: config.botImg,
            url: config.botUrl,
          },
          description:
            "<@767456705306165298>, click the tite to go purchase!\n\n" +
            "Price: " +
            symbol +
            price,
          thumbnail: {
            url: image,
          },
          timestamp: new Date(),
        };

        // NOTE: you might want to wait for this too, the error
        // currently isn't being handled like this either.
        message.channel.send({ embed: inStockResponse });
        console.log(title + " (" + asin + ") IS available!");
      } else {
        console.log(title + " (" + asin + ") IS NOT available!");
      }
    } catch (err) {
      console.log(err);
    }
  }

  // Wait 30s and check again.
  setTimeout(() => checkItems(items), 30000);
}

checkItems(config.items.itemGroup);