4

コールバックと非同期プログラミングを理解しようとしていますが、少し問題があります。

ここにいくつかの擬似コードがあります:

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 を返します。私はそれを理解していますが、多くの複雑な方法を試しましたが、適切な書き方がわかりません。どんな助け/説明も大歓迎です。私はたくさんのチュートリアルと例を読んだ (そして今も読んでいる) が、それを得る唯一の方法は自分でコードを書くことだと思う. これを解決したら、答えを投稿します。

4

5 に答える 5

2

Node での非同期プログラミングをもう少しよく理解するのに役立つかもしれない Node の紹介については、この記事を確認してください。

非同期プログラミングに関する限り、asyncは Node のユーザーランドで非常に人気のあるモジュールであり、非同期コードを簡単に作成するのに役立ちます。たとえば(テストされていない疑似コード):

function scrape (done) {
  http.get(url, done);
}

function parse (res, done) {
  var lines = [];

  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 () {
          done(null, lines);
        });
}

function done (err, lines) {
  if (err) { throw err; }

  console.log(lines.length);
}

async.waterfall([scrape, parse], done);
于 2013-10-28T16:17:06.893 に答える
1

わかりましたので、これが私が問題を解決した方法です。お気軽にコメントして、それが正しいかどうか教えてください。

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);

すべての回答に感謝します。もっと複雑なことをしなければならないので、非同期についてさらに詳しく調べています。私のコードについてどう思うか教えてください。それは常に役に立ちます。

于 2013-10-28T19:52:07.893 に答える
1

これは、すべての URL を並行してスクレイピングするか、連続してスクレイピングするかによって異なります。

シリーズで行う場合は、次のように考える必要があります。

最初の URL から始めます。こする。コールバックで、次の URL を取得します。コールバックで、次の URL を取得します。

これは、あなたが話している悪名高いコールバック地獄をもたらしますが、それは少なくとも原則です. async などのライブラリが多くの頭痛の種を取り除きます。

于 2013-10-28T16:20:18.440 に答える
1

この方法で非同期呼び出しをプログラミングする場合、最後にチェーンする関数と命令 ( など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);
    }
}

また、コールバック地獄を回避することを目的とした、コールバックに代わるプログラミング スタイルであるpromisesを調べることもできます。

于 2013-10-28T16:20:31.940 に答える
1

私はnode.jsに非常に慣れておらず、コールバックを理解するのに苦労していることを認めなければなりません。私の限られた経験では、コールバック関数にパラメーターをもう 1 つ追加するのがコツかもしれません。難しい質問は、どのパラメーターですか?

あなたの例では、関数scrapeに追加のブール値「lastOne」がある場合、それは console.log(lines) 自体を呼び出すことができます。または、null URL が停止することを意味することを理解した場合。 ただし、すべてが順番に行われるかどうかわからないため、これでもうまくいくとは思いません。2 番目の URL が永遠に続く場合、最後の URL が最初に完了する可能性がありますよね??? (あなたはそれを試すことができます)。つまり、どのパラメーターを追加すればよいのか、まだわかりません。ごめん...

より信頼できると思われるのは、カウンターを urls.length に設定し、scrape()毎回それをデクリメントすることです。カウンターが 0 に達すると、プロセス全体が完了したことを認識し、結果をログに記録する (または何でもする) 必要があります。このカウンターを宣言する場所が 100% わかりません。Javaから来て、静的グローバルとは何か、インスタンスとは何か、まだほとんどわかりません...

ここで、真の青色の node.jser は、関数を doWhatever に追加のパラメーターとして渡し、scrape()以外のことを実行できるようにしますconsole.log()。:-) しかし、ゼロのチェックで解決します。

少し詳しく説明するには、callWhenDoneパラメーターをscrape()に追加し、追加します (すべてのネストのどこかに!!!)

if (--counter <= 0)
  callWhenDone (lines);
于 2013-10-28T18:42:20.703 に答える