Javascript 如何在for循环中使用node.js中的Request函数并使其以正确的顺序返回输出?
我一直在使用request遍历几个XML条目,并使用cheerio.js将每一篇文章、日期和url返回到控制台。主要的问题是每次输出都会以不同的顺序出现,因为请求是一个异步函数。一般来说,我对javascript缺乏经验,想知道如何检索一致的输出(我一直在阅读有关异步和承诺的文章,我只是不确定如何实现它们)。 这是我的密码:Javascript 如何在for循环中使用node.js中的Request函数并使其以正确的顺序返回输出?,javascript,node.js,request,cheerio,Javascript,Node.js,Request,Cheerio,我一直在使用request遍历几个XML条目,并使用cheerio.js将每一篇文章、日期和url返回到控制台。主要的问题是每次输出都会以不同的顺序出现,因为请求是一个异步函数。一般来说,我对javascript缺乏经验,想知道如何检索一致的输出(我一直在阅读有关异步和承诺的文章,我只是不确定如何实现它们)。 这是我的密码: var count = 0; for(var j = 0; j < arrNames.length; j++){ request('http://dblp.org
var count = 0;
for(var j = 0; j < arrNames.length; j++){
request('http://dblp.org/search/publ/api?q=' + arrNames[j], function(error, response, html){
if (!error && response.statusCode == 200){
var $ = cheerio.load(html, {xmlMode: true});
console.log($('query').text()+'\n');
$('title').each(function(i, element){
var title = $('title').eq(i).text();
var year = Number($('year').eq(i).text());
var url = $('ee').eq(i).text();
if (year >= arrTenures[count]){
console.log(title);
console.log(year);
console.log(url + '\n');
}
});
count++;
}
});
}
var计数=0;
对于(var j=0;j=任期[计数]){
控制台日志(标题);
对数(年);
console.log(url+'\n');
}
});
计数++;
}
});
}
看起来您正试图捕获每个请求的迭代次数,因此请使用forEach
并使用其第二个参数,该参数指示迭代索引:
arrNames.forEach((q, requestIndex) => {
request('http://dblp.org/search/publ/api?q=' + q, (error, response, html) => {
if (error || response.statusCode == 200) return;
var $ = cheerio.load(html, {
xmlMode: true
});
console.log($('query').text() + '\n');
$('title').each(function(i, element) {
var title = $('title').eq(i).text();
var year = Number($('year').eq(i).text());
var url = $('ee').eq(i).text();
if (year >= arrTenures[requestIndex]) {
console.log(title);
console.log(year);
console.log(url + '\n');
}
});
});
});
作为一个旁注,一致的缩进确实提高了代码可读性——您可以考虑一个LITER。
在您的第一次尝试中,您可能已经尝试过:
if (year >= arrTenures[j]) {
但我注意到这不起作用。这是因为范围界定问题
您可以通过使用迭代器(如forEach()
)或简单地将for循环更改为使用let
)来解决问题:
for(let j = 0; j < arrNames.length; j++){
虽然您已经找到了解决方案,但我想我会向您展示如何使用ES6 Promissions(一种管理多个异步操作的更现代的方法)来实现这一点: 这有几个优点:
Promise.all()
为您整理结果rp()
为您检查2xx状态如果您使用promises,它将是这样的
Promise.all(arrNames.map(name=>request(“http://dblp.org/search/publ/api?q=“+name”)。然后(arrayWithResult=>{/*在这里做你的事*/})
非常感谢您的快速回复!您在我尝试捕获每个请求的迭代编号时说得非常正确,这正是解决问题的方法!而且我的缩进在现实生活中稍微好一点,这是我第一次在so上发布,所以我搞砸了格式。谢谢!我不知道您可以用Javascript中的数组,谢谢你的想法!然后你可以做item.name
或item.tenures
:)哈,我只是在谷歌上搜索如何访问这些元素!谢谢这是一个非常有帮助的回答,如果所有的东西都按顺序退回,那将是非常好的。这使得承诺看起来不像我想象的那么困难,很难从无关的例子中收集。谢谢
[
{ name: 'some name', tenures: 2 },
{ name: 'another', tenures: 5 }
]
const rp = require('request-promise');
Promise.all(arrNames.map(item => {
return rp('http://dblp.org/search/publ/api?q=' + item).then(html => {
const $ = cheerio.load(html, {xmlMode: true});
return $('title').map(function(i, element){
const title = $(element).text();
const year = Number($('year').eq(i).text());
const url = $('ee').eq(i).text();
return {title, year, url};
}).get();
});
})).then(results => {
// results is an array of arrays, in order
console.log(results);
}).catch(err => {
console.log(err);
});