Javascript 节点,异步编程,回调地狱

Javascript 节点,异步编程,回调地狱,javascript,node.js,asynchronous,Javascript,Node.js,Asynchronous,我试图理解回调和异步编程,但我遇到了一些麻烦 下面是一些伪代码: var lines = []; var arrayOfFeedUrls = [url1,url2,...]; function scrape(url){ http.get(url, function(res) { res.pipe(new FeedParser([options])) .on('readable', function () { var stream

我试图理解回调和异步编程,但我遇到了一些麻烦

下面是一些伪代码:

var lines = [];
var arrayOfFeedUrls = [url1,url2,...];

function scrape(url){
    http.get(url, function(res) {
        res.pipe(new FeedParser([options]))
        .on('readable', function () {
            var stream = this, item;
            while (item=stream.read()) {
                line = item.title;
                lines.push(line);
            }
        });
    });
});

for (i in arrayOfFeedUrls){
    scrape(arrayOfFeedUrls[i];
}
console.log(lines.length);
它显然返回0,因为scrape函数是异步执行的。我明白很多,但我已经尝试了很多复杂的方法,不知道如何正确地编写它。如有任何帮助/解释,将不胜感激。我已经读过(现在还在读)很多教程和例子,但我认为我获得它们的唯一方法是自己编写一些代码。如果我解决了这个问题,我会发布答案。

您可以查看Node中的介绍,这可能会帮助您更好地理解Node中的异步编程

就异步编程而言,它是节点用户区中非常流行的模块,可以帮助您轻松地编写异步代码。例如(未测试的伪代码):


这取决于您是希望并行还是串行地刮取所有URL

如果你要连续做,你应该这样想:

从第一个url开始。刮在回调中,刮取下一个url。在回调中,刮取下一个url


这将给你所说的臭名昭著的回调带来地狱,但这至少是原则。像async之类的库消除了很多麻烦。

以这种方式编程异步调用时,您希望链接到末尾的函数和指令,例如
console.log(lines.length),也必须是回调。举个例子,试着这样做:

var lines = [];
var arrayOfFeedUrls = [url1,url2,...];

function scrape(url){
    http.get(url, function(res) {
        res.pipe(new FeedParser([options]))
        .on('readable', function () {
            var stream = this, item;
            while (item=stream.read()) {
                line = item.title;
                lines.push(line);
                done();
            }
        });
    });
});

for (i in arrayOfFeedUrls){
    scrape(arrayOfFeedUrls[i];
}
function done () {
    if (lines.length == arrayOfFeedUrls.length) {
        console.log(lines.length);
    }
}

您可能还想研究回调的另一种编程风格,其目的是避免回调地狱。

必须承认,我对node.js非常陌生,正在努力摸索回调的东西。根据我有限的经验,在回调函数中再添加一个参数可能是一个技巧。困难的问题是,哪个参数

在您的示例中,如果函数
scrape
有一个额外的布尔值“lastOne”,那么它可以调用console.log(行)。或者,如果它理解空url意味着停止。然而,我认为即使这样也行不通,因为我不确定一切都会按顺序完成。如果第二个URL需要很长时间,最后一个可能会先完成,对吗???(你可以试试看)。换句话说,我仍然不知道要添加哪个参数。对不起

似乎更可靠的方法是将计数器设置为url.length,并为
scrap()
每次递减。当计数器达到0时,它知道整个过程已经完成,它应该记录(或执行任何操作)结果。我不能百分之百确定在哪里申报这个柜台。来自Java的我仍然不知道什么是静态全局,什么是实例,无论什么

现在,一个真正的blue node.jser将向doWhatever传递一个函数,作为
scrape()
的额外参数,这样您就可以执行
console.log()
:-)以外的操作了但我愿意接受零的支票

稍微详细说明一下,将
callWhenDone
参数添加到
scrap()
,然后添加(在所有嵌套中的某个地方!!!)


if(--counter好的,下面是我如何解决这个问题的,请随意评论并告诉我它是否正确

var lines = [];
var arrayOfFeedUrls = [url1,url2,...];

function scrape(array){
    var url = array.shift();
    http.get(url, function(res) {
        res.pipe(new FeedParser([options]))
        .on('readable', function () {
            var stream = this, item;
            while (item=stream.read()) {
                line = item.title;
                lines.push(line);
            }
        }).on('end', function () {
            if(array.length){
                scrapeFeeds(array);
            }
        });
    });
});

scrapeFeeds(array);

感谢所有的答案,我正在更深入地研究异步,因为我有更复杂的事情要做。让我知道你对我的代码的看法,它总是有用的。

看看承诺。我认为它们是避免回调地狱的最优雅的方式。虽然异步库可以解决这个问题,但它没有解释应该如何解决。PromISE很花哨,但命名和取消嵌套回调将大大减少混乱和混乱;只需传递将关闭的内容即可,这有助于记录您的过程。这至少是承诺的一半,但需要更少的努力和学习。简言之,如果char(()正好出现在chars“函数”之后,你做错了。我不认为lines.length与url.length匹配,因为每个url可能有多行。(我认为)。但我认为你的思路是正确的-请查看我的答案并发表评论,如果你认为这是一种改进(或不是),请检查我的答案,里面有一点你的:)
if (--counter <= 0)
  callWhenDone (lines);
var lines = [];
var arrayOfFeedUrls = [url1,url2,...];

function scrape(array){
    var url = array.shift();
    http.get(url, function(res) {
        res.pipe(new FeedParser([options]))
        .on('readable', function () {
            var stream = this, item;
            while (item=stream.read()) {
                line = item.title;
                lines.push(line);
            }
        }).on('end', function () {
            if(array.length){
                scrapeFeeds(array);
            }
        });
    });
});

scrapeFeeds(array);