Javascript 在nodeJS中创建异步while循环
在堆栈中有几个类似的问题,但我不能得到任何适合我的答案,我对Node和异步编程的概念是完全陌生的,所以请耐心听我说 我正在构建一个目前有4步流程的刮板:Javascript 在nodeJS中创建异步while循环,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,在堆栈中有几个类似的问题,但我不能得到任何适合我的答案,我对Node和异步编程的概念是完全陌生的,所以请耐心听我说 我正在构建一个目前有4步流程的刮板: 我给它一个链接集合 它转到每个链接,在页面上找到所有相关的img src 它找到“下一页”链接,获取其href,从所述href检索dom,并重复步骤2 所有这些imgsrc都被放入一个数组中并返回 这是密码getLinks可以异步调用,但其中的while循环当前无法: function scrape(url, oncomplete) {
img src
href
,从所述href
检索dom,并重复步骤2imgsrc
都被放入一个数组中并返回getLinks
可以异步调用,但其中的while
循环当前无法:
function scrape(url, oncomplete) {
console.log("Scrape Function: " + url);
request(url, function(err, resp, body) {
if (err) {
console.log(UHOH);
throw err;
}
var html = cheerio.load(body);
oncomplete(html);
}
);
}
function getLinks(url, prodURL, baseURL, next_select) {
var urls = [];
while(url) {
console.log("GetLinks Indexing: " + url);
var html = scrape(url, function(data) {
$ = data;
$(prodURL).each(function() {
var theHref = $(this).attr('href');
urls.push(baseURL + theHref);
}
);
next = $(next_select).first().attr('href');
url = next ? baseurl + next : null;
}
);
}
console.log(urls);
return urls;
}
目前,这进入了一个无限循环,没有任何刮擦。如果我把url=next?baseurl+next:空代码>在回调之外,我得到一个“next”未定义的错误
关于如何重新处理此问题以使其对节点友好有何想法?从这个问题的本质来看,它似乎需要阻塞,不是吗?这是一种常见的模式,您希望执行循环,但使用带有回调的异步函数。由于不能等待异步函数,因此不能简单地使用while循环
一种解决方案是使用“堆栈”(或数组)。用您要处理的初始元素填充此字段。当您发现更多要处理的元素时,请将它们添加到此堆栈。并递归调用函数递增要处理的索引,直到索引超过数组的长度
e、 g
函数do\u scrape(堆栈、此url、回调){
//从该url处的网页获取url列表
...
stack.push(new_url);//向数组添加新元素
...
...
callback();//进程回调
}
函数进程堆栈(URL的堆栈,idx){
var this_url=stack_of_url[idx];
刮擦(
一堆URL,
这个网址,,
函数(){
if(idx+1
注意,有很多方法可以实现这一点。为了提高效率,您可以从堆栈中删除已处理的元素。您还可以选择是从头到尾处理堆栈,还是从头到尾处理堆栈,等等。最后请注意,如果在do_scrape
函数中不调用异步函数,那么将有一个很紧的回调循环,node.js将中止,抱怨堆栈太大。将while循环重写为递归函数。然后,您将很容易识别如何通过传递回调来实现异步。@Bergi啊,原来我只需要知道名称,我就可以自己解决它了。对于任何一个偶然发现这一点的人来说:这是一个很好的资源
function do_scrape( stack, this_url, callback ) {
// get list of URLs from webpage at this_url
...
stack.push( new_url ); // adding new element to array
...
...
callback(); // process callback
}
function process_stack( stack_of_urls, idx ) {
var this_url = stack_of_urls[idx];
do_scrape(
stack_of_urls,
this_url,
function () {
if ( idx + 1 < stack_of_urls.length ) {
process_stack( stack_of_urls, (idx + 1) );
} else {
process.exit( 0 );
}
}
);
}
var stack_of_urls = [ "http://www.yahoo.com/" ];
process_stack( stack_of_urls, 0 ); // start from index zero