我尝试使用异步的ruipgil / scraperjs函数制作一个刮刀。但是当我把它放在一个循环中时,它就会卡住并且不会起作用。我是Node的新手和异步编程的想法所以请耐心等待。
所以,我有这段代码:
let scraperjs = require('scraperjs');
// scraper function
function scrape(pageURI, callback) {
console.log('checkpoint 2'); // checkpoint
scraperjs.StaticScraper.create(pageURI).scrape(function($) {
console.log('checkpoint 3'); // checkpoint
return $("div").map(function() {
return $(this).text();
}).get();
}).then(function(sometext) {
callback(sometext);
});
}
// loop function
function testloop() {
let finished = false;
let processed = false;
while (!finished) {
if (!processed) {
console.log('checkpoint 1'); // checkpoint
scrape('https://www.google.com/', (sometext) => {
console.log('checkpoint 4', sometext); // checkpoint
finished = true;
});
processed = true;
}
}
}
// non loop function
function testnonloop() {
console.log('checkpoint 1'); // checkpoint
scrape('https://www.google.com/', (sometext) => {
console.log('checkpoint 4', sometext); // checkpoint
});
}
我试图调度两个期望完整的4个检查点输出的函数。但奇怪的是,带有循环的那个在检查点2中被卡住而且从未进展过。 [我也尝试使用promise而不是回调样式,但仍然是相同的输出。]
我哪里出错?
答案 0 :(得分:1)
您可以尝试使用递归,这样它就不会卡在那个循环中吗?
// loop function
function testloop() {
console.log('checkpoint 1'); // checkpoint
scrape('https://www.google.com/', (sometext) => {
console.log('checkpoint 4', sometext); // checkpoint
testLoop();
});
}
答案 1 :(得分:1)
问题是while
循环中的条件永远不会改变,因为回调函数永远不会被执行。
这是因为JavaScript程序在事件循环中执行。 JavaScript引擎有调用堆栈(记录我们在程序中的位置)和回调队列(跟踪要执行的异步回调)。
事件循环监控呼叫堆栈和回拨队列。如果调用堆栈为空,它将从回调队列中获取第一个事件,并将其推送到运行它的调用堆栈。
在你的情况下,调用堆栈永远不会变空,它总是忙于while
循环,因此永远不会执行回调,所以while
条件总是{ {1}}。
可能的解决方案是使用true
来调用setTimeout
,直到第一个回调被调用。使用scrape
,您将释放调用堆栈,让异步调用执行。
setTimeout
您可以在此处找到有关事件循环的更深入说明:How JavaScript works: an overview of the engine, the runtime, and the call stack