等待多个Cheerio“ .each”循环中的异步查询

时间:2019-05-30 22:23:16

标签: javascript node.js express asynchronous cheerio

我已经使用axios.all方法建立了一个后端路由,该方法从三个不同的站点提取数据,然后将它们抓取到Axios .then块中。我正在使用Cheerio的.each循环方法来抓取匹配的文章标题,图像链接和故事链接,但是在.each循环的每次运行中,我还想将每篇文章的详细信息存储到MongoDB中数据库。是否有一种方法可以等待.each循环中的那些查询,或者以某种方式将三个.each循环包装在promise中,以便所有抓取和数据库查询都在触发res.send('Scrape complete')之前发生? / p>

我尝试将另一个.then方法链接到第一个.then方法,但是在完成.each循环中的所有异步查询之前,它仍然继续进行下去。我还尝试将三个.each方法包装在Promise类中。

这是当前的后台文章抓取功能

router.get('/articleScrape', (req, res) => {
  axios
    .all([
      axios.get('https://thespool.net/'),
      axios.get('https://www.overthinkingit.com/'),
      axios.get('https://filmschoolrejects.com/'),
    ])
    .then(
      axios.spread((spoolRes, overthinkingRes, filmSchoolRes) => {
        const spool = cheerio.load(spoolRes.data);
        const over = cheerio.load(overthinkingRes.data);
        const fsr = cheerio.load(filmSchoolRes.data);

        spool('div .hover__handler').each(function (i, element) {
          const result = {};

          result.title = spool(this)
            .children('header')
            .children('a')
            .children('h1')
            .text()
            .replace('\n', '');
          result.siteURL = 'thespool.net';
          result.linkURL = spool(this)
            .children('header')
            .children('a')
            .attr('href');
          result.imgURL = spool(this)
            .children('aside')
            .children('img')
            .attr('src');

          db.Article.findOne({ title: result.title }).then((searchedArticle) => {
            if (!searchedArticle) {
              db.Article.create(result)
                .then((dbArticle) => {
                  console.log(dbArticle);
                })
                .catch((err) => {
                  console.log(err);
                });
            }
          });
        });

        over('.post').each(function (i, element) {
          const result = {};

          result.title = over(this)
            .find('h2')
            .text();
          result.siteURL = 'overthinkingit.com';
          result.linkURL = over(this)
            .find('.entry--archive__title-link')
            .attr('href');
          result.imgURL = over(this)
            .find('img')
            .attr('src');

          db.Article.findOne({ title: result.title }).then((searchedArticle) => {
            if (!searchedArticle) {
              db.Article.create(result)
                .then((dbArticle) => {
                  console.log(dbArticle);
                })
                .catch((err) => {
                  console.log(err);
                });
            }
          });
        });

        fsr('article').each(function (i, element) {
          const result = {};

          result.title = fsr(this)
            .find('h3')
            .text();
          result.siteURL = 'filmschoolrejects.com';
          result.linkURL = fsr(this)
            .find('h3')
            .children('a')
            .attr('href');
          result.imgURL = fsr(this)
            .find('img')
            .attr('data-src');

          db.Article.findOne({ title: result.title }).then((searchedArticle) => {
            if (!searchedArticle) {
              db.Article.create(result)
                .then((dbArticle) => {
                  console.log(dbArticle);
                })
                .catch((err) => {
                  console.log(err);
                });
            }
          });
        });

        res.send('Scrape complete');
      }),
    );
});

我想确保在我第二次调用数据库以检索刚创建的文章之前完成此刮擦,这是通过第二条路线进行的:

router.get('/articles', (req, res) => {
  db.Article.find({})
    .then((dbArticles) => {
      res.json(dbArticles);
    })
    .catch((err) => {
      res.json(err);
    });
});

最后,这是前端在页面加载时的调用顺序:

axios.get('/data/articleScrape').then(async (response) => {
  console.log(response);
  getArticles();
});

function getArticles() {
  axios.get('/data/articles').then((response) => {
    console.log(response.data);
  });
}

我想要的是确保刮擦已完全完成,以便当我运行第二次调用以从数据库中获取文章时,它们就在那里了。我知道问题出在.each循环中发生的异步调用中,但是我似乎找不到完美的解决方案。有帮助吗?

0 个答案:

没有答案