如下所示,我将对象link_to_json
返回到allShirts
中声明的数组html_to_json
。
但是,最后一行的console.dir
和html_to_json
的返回值记录了一组未定义的引用。我认为是因为console.dir
和return
在link_to_json
函数完成之前执行。
如何确保html_to_json
的返回值是填充的allShirts
数组?
//Go to individual links and scrape relevant info
const link_to_json = (link) => {
request(link, (err, res, body) => {
if (!error_handler(err, res, link)) {
const $ = cheerio.load(body);
const shirt_detail = $('.shirt-details').find('h1').text();
const Title = shirt_detail.substr(shirt_detail.indexOf(' ') + 1);
const Price = shirt_detail.substr(0, shirt_detail.indexOf(' '));
const ImageURL = $('.shirt-picture').find('img').attr('src');
const URL = link;
return new Shirt(Title, Price, ImageURL, URL);
} else return {};
});
}
//Crawl through all individual links listed in Root
const html_to_json = body => {
const allShirts = [];
const $ = cheerio.load(body);
$('.products').find('a').each((index, val) => {
allShirts.push(link_to_json(rootURL + $(val).attr('href')));
});
console.dir(allShirts); // <--- HERE
return allShirts;
}
答案 0 :(得分:2)
有几种方法可以解决这个问题,但我喜欢这个Async库。
我如何处理你的问题的方法是先实际获取所有的网址,这样就可以改变你的身体了:
const shirtLinks = [];
$('.products').find('a').each((index, val) => {
shirtLinks.push(rootURL + $(val).attr('href'));
});
您还需要转换功能是异步的:
const linkToJSON = (link, cb) => {
request(link, (err, res, body) => {
if (!error_handler(err, res, link)) {
const $ = cheerio.load(body);
const shirt_detail = $('.shirt-details').find('h1').text();
const Title = shirt_detail.substr(shirt_detail.indexOf(' ') + 1);
const Price = shirt_detail.substr(0, shirt_detail.indexOf(' '));
const ImageURL = $('.shirt-picture').find('img').attr('src');
const URL = link;
return cb(null, new Shirt(Title, Price, ImageURL, URL));
}
return cb();
});
}
然后使用async将它们映射到提取数据的异步函数:
async.map(shirtLinks, linkToJSON, (err, results) => {
console.dir(results);
});
答案 1 :(得分:2)
我就是这样做的。我发现以这种方式调试更容易。
let getShirtDetailsBody = (link) => {
return new Promise((resolve, reject) => {
request(link, (err, res, body) => {
if (err) {
reject(err)
} else {
resolve(body)
}
})
})
}
let getShirt = (body) => {
const $ = cheerio.load(body);
const shirt_detail = $('.shirt-details').find('h1').text();
const Title = shirt_detail.substr(shirt_detail.indexOf(' ') + 1)
const Price = shirt_detail.substr(0, shirt_detail.indexOf(' '))
const ImageURL = $('.shirt-picture').find('img').attr('src')
const URL = link
return new Shirt(Title, Price, ImageURL, URL)
}
let getAllProductsShirtsBody = (body) => {
const $ = cheerio.load(body)
return Promise.all($('.products').find('a').map((index, val) => {
return getShirtDetailsBody(`rootURL${$(val).attr('href')}`)
}))
}
getAllProductsShirtsBody(yourbody).then(allShirtsBody => {
const allShirts = allShirtsBody.map(shirtBody => { return getShirt(shirtBody) })
console.log(allShirts)
}).catch(err => { console.log(err) })
&#13;