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