Вложенные async.eachSeries стекируют итерации

78
11

Следующая функция получает массив ссылок и сканирует удаленный веб-сайт, получает 10 сообщений в блоге на страницу, а затем каждый комментарий для сообщения в блоге, используя async.waterfall.

// @param {Array} url
export default function getData(url, cb) {
const arrayOfPosts = [];
// Outer loop
async.eachSeries(url, (link, topLVLcb) => {

// Waterfall
async.waterfall([

// Collects links to posts
callback => {
request(link, (err, response, body) => {
console.log('working on ${link}');

const $ = cheerio.load(body);

// OVERALL 10 LINKS PER ONE BLOGPOST
$('.blogpost').each((i, element) => {

// build post ojbect

const post = {
content,
link,
comments: []
}
arrayOfPosts.push(post);
});
callback(null, arrayOfPosts);
});
},

// Looks for details in given post
(arrOfPosts, postDetailsCallback) => {
let counter = 1;

// Inner loop through 10 links
async.eachSeries(arrOfPosts, (post, eachSeriesCallback) => {
request(post.link, (err, response, body) => {
console.log(counter++);
const $ = cheerio.load(body);
$('.comment').each((i, element) => {

// build comment

const comment = {
author,
content
};

post.comments.push(comment);
});
eachSeriesCallback(null);
});
}, postDetailsCallback);
}
], err => {
console.log('DONE PAGE');
console.log('*************************');
topLVLcb(err);
});
}, (result, err) => {
if (err) {
throw err;
} else {
console.log('DONE ALL');
cb(arrayOfPosts);
}
});
}

Он обеспечивает вывод следующим образом:

working on www.mywebsite.com/
1
2
3
4
5
6
7
8
9
10
DONE PAGE
**************************************************************
working on www.mywebsite.com/posts/1
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
DONE PAGE
**************************************************************

И он увеличивает каждую страницу на десять, начиная с каждой итерации. Пока он сканирует каждую страницу 10 раз. Я думаю, что я испортил некоторые из обратных вызовов, но я не могу понять точно ровно столько часов. Это мой первый асинхронный код nodejs, и он очень подавляющий.

спросил(а) 2021-01-25T19:21:27+03:00 4 месяца, 4 недели назад
1
Решение
63

arrayOfPost[] является глобальным для каждого async.waterfall... для каждого элемента url в url arrayOfPost[] вы должны создать новый arrayOfPost[] как arrayOfPost[] ниже....


export default function getData(url, cb) {
const arrayOfPosts = [];
// Outer loop
async.eachSeries(url, (link, topLVLcb) => {
var tmpArr=[];
// Waterfall
async.waterfall([

// Collects links to posts
callback => {
request(link, (err, response, body) => {
console.log('working on ${link}');

const $ = cheerio.load(body);

// OVERALL 10 LINKS PER ONE BLOGPOST
$('.blogpost').each((i, element) => {

// build post ojbect

const post = {
content,
link,
comments: []
}
tmpArr.push(post);
arrayOfPosts.push(post);
});
callback(null, tmpArr);//this tmpArr which is being passed will always cantain 10 items(posts) so there will be 10 iterations for each element in url
});
},

// Looks for details in given post
(arrOfPosts, postDetailsCallback) => {
let counter = 1;

// Inner loop through 10 links
async.eachSeries(arrOfPosts, (post, eachSeriesCallback) => {
request(post.link, (err, response, body) => {
console.log(counter++);
const $ = cheerio.load(body);
$('.comment').each((i, element) => {

// build comment

const comment = {
author,
content
};

post.comments.push(comment);
});
eachSeriesCallback(null);
});
}, postDetailsCallback);
}
], err => {
console.log('DONE PAGE');
console.log('*************************');
topLVLcb(err);
});
}, (result, err) => {
if (err) {
throw err;
} else {
console.log('DONE ALL');
cb(arrayOfPosts);
}
});
}

ответил(а) 2021-01-25T19:21:27+03:00 4 месяца, 4 недели назад
63

Похоже, что вы сохраняете все сообщения в верхнем уровне arrayOfPosts но это означает, что в вашей второй функции водопада вы будете обрабатывать все сообщения с самого начала с тех пор, как вы переходите к обратному вызову. Итак, в вашем первом обратном вызове, который собирает ссылки на сообщения, вы должны иметь локальный массив сообщений, которые вы перешли к следующему обратному вызову.

ответил(а) 2021-01-25T19:21:27+03:00 4 месяца, 4 недели назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема