Ожидание асинхронных запросов в нескольких циклах Cheerio ".each" - PullRequest
0 голосов
/ 31 мая 2019

Я настроил внутренний маршрут с помощью метода axios.all, который извлекает данные из трех разных сайтов, которые я затем очищаю в блоке Axios .then.Я использую метод зацикливания .each в Cheerio для поиска подходящих названий статей, ссылок на изображения и ссылок на истории, но в каждом цикле цикла .each я также хочу сохранить детали каждой статьи в базе данных MongoDB.Есть ли способ ожидания этих запросов в цикле .each или какой-либо способ обернуть три цикла .each в обещание, чтобы все операции очистки и запросов к базе данных происходили до запуска res.send('Scrape complete')?

Iпопытался связать другой метод .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, но я не могу найти элегантное решение.Любая помощь?

...