Javascript Array.forEach中的Node.Js异步请求在编写json文件之前未完成
我正在制作一个web scraper Node.js应用程序,它可以从各种URL获取工作描述文本。。我目前有一个名为jobObj的作业对象数组,代码在每个url中循环,对html发出请求,使用cheerio模块加载然后最终使用jobName和jobDesc键创建一个新对象,并将其推送到一个新的对象数组中,然后将其写入json文件 所有这些目前都有效,但是编写的json文件的完整性是非常随机的,通常只包含一个完整的作业帐户。我认为这可能是因为forEach循环完成得比异步请求函数快得多,从而导致在请求回调完成之前执行fs.writefile。我添加了一个计数器来监视请求处于哪个阶段,并且只在counter==jobObj.length写入json文件一次,但json文件仍然没有完全完成 我是node.js新手,如果有人能指出我的错误,我将不胜感激Javascript Array.forEach中的Node.Js异步请求在编写json文件之前未完成,javascript,json,node.js,request,cheerio,Javascript,Json,Node.js,Request,Cheerio,我正在制作一个web scraper Node.js应用程序,它可以从各种URL获取工作描述文本。。我目前有一个名为jobObj的作业对象数组,代码在每个url中循环,对html发出请求,使用cheerio模块加载然后最终使用jobName和jobDesc键创建一个新对象,并将其推送到一个新的对象数组中,然后将其写入json文件 所有这些目前都有效,但是编写的json文件的完整性是非常随机的,通常只包含一个完整的作业帐户。我认为这可能是因为forEach循环完成得比异步请求函数快得多,从而导致在
var jobObj = [
{
id:1,
url:"https://www.indeed.co.uk/cmp/Daffodil-IT/jobs/Lead-Junior-Website-Developer-59ea7d446bdf1253?q=Junior+Web+Developer&vjs=3",
},
{
id:2,
url:"https://www.indeed.co.uk/cmp/Crush-Design/jobs/Middleweight-Web-Developer-541331b7885c03cf?q=Web+Developer&vjs=3",
},
{
id:3,
url:"https://www.indeed.co.uk/cmp/Monigold-Solutions/jobs/Graduate-Web-Software-Engineer-a5787dc322c0ca36?q=Web+Developer&vjs=3",
},
{
id:4,
url:"https://www.indeed.co.uk/cmp/ZOO-DIGITAL-GROUP-PLC/jobs/Web-Developer-5cdde1c3b0b7b8d0?q=Web+Developer&vjs=3",
},
{
id:5,
url:"https://www.indeed.co.uk/viewjob?jk=9cc3d8c637c41067&q=Web+Developer&l=Sheffield&tk=1cf5di52e9u0ocam&from=web&vjs=3",
}
];
app.get('/myform', function(req, res){
res.send("<h1>" + `scanning ${jobObj.length} urls for job description text` + "</h1>");
//make assign input form data to node "url" variable
//Compnonents for a request counter
var jobs = new Array;
function scrapeFinished(){console.log("all websites scraped!");};
var itemsProcessed = 0;
jobObj.forEach(function(item){
request(item.url, function(err, res, html){
if(!err){
var $ = cheerio.load(html);
var newJob = new Object;
$('#job_summary').each(function(){
var data = $(this);
var textout = data.text();
newJob.jobDesc = textout;
});
$('.jobtitle').each(function(){
var data = $(this);
var jobtitle = data.text();
newJob.jobName = jobtitle;
});
jobs.push(newJob);
itemsProcessed++;
console.log(item.url + " scraped");
if(itemsProcessed === jobObj.length){
scrapeFinished();
fs.writeFile('output.json', JSON.stringify(jobs, null, "\t"), function(err){
if(!err){console.log("output.json file written")}
})
}
}
})
})
})
forEach以同步方式运行,因此无论需要多少时间来废弃网页,它都不会为下一个数组项运行。这里可能会出现问题的是,您的代码可能会在销毁网页之前在数组中推送一个对象。这就是为什么会得到一个空对象。您要做的是在程序访问完URL后推送对象。
做这样的事
jobObj.forEach(function (item) {
var newJob = new Object;
request(item.url, function (err, res, html) {
// Scrap URL and save values in newJob
});
jobs.push(newJob);
});
如果代码在完成请求之前仍推空对象,则考虑使用模块。 移动push()没有解决问题,但确实导致总共有3个工作帐户完成!当前pb!将有一个与异步模块,干杯!虽然异步请求会在等待回调时跳到push()函数吗?不会。我不这么认为。将push()移到请求之外后,新的输出是什么?
jobObj.forEach(function (item) {
var newJob = new Object;
request(item.url, function (err, res, html) {
// Scrap URL and save values in newJob
});
jobs.push(newJob);
});