2013-12-10 24 views
6

私はNode.jsといくつかの非同期操作の周りに頭を抱えています。次のコードでは、いくつかのRSSフィードを取得し、以前に保管していない記事を保管します。コードは新しい記事を処理して保存します。しかし、私はすべての記事が解析された時点を知るためにこれを変更する方法がわかりません。たとえば、各async.eachLimitのコールバックは、制限が満たされるたびに呼び出されます(記事10件またはフィード5件後)。だから、彼らはいつ終わったのか分かりますか?node.js async.eachコールバック、完了時はどうすればわかりますか?

var FeedParser = require('feedparser'); 
var request = require('request'); 
var mysql = require('mysql'); 
var async = require('async'); 

var connection = mysql.createConnection({ 
     host : 'localhost', 
     user : 'someuser', 
     password : 'somepass', 
     database : 'somedb' 
}); 

connection.connect(); 

connection.query('SELECT * FROM rssfeed', function(err, rows, fields) { 
     if(err == null){ 
       async.eachLimit(rows, 5, parseFeed, function(err) { 
         if(! err) { 
           //horray 
         } else { 
           console.log(err); 
         } 
       }); 
     } 
}); 

function parseFeed(feed, callback) { 
     var articles = []; 
     request(feed.link) 
     .pipe(new FeedParser()) 
     .on('error', function(error) { 
       callback(error); 
     }) 
     .on('meta', function(meta) { 
     }) 
     .on('readable', function() { 
       var stream = this, item; 
       item = stream.read(); 
       if(item != null) { 
         item.rssfeed_id = feed.id; 
         articles.push(item); 
       } 
     }) 
     .on('finish', function() { 
       async.eachLimit(articles, 10, parseArticle, function(err) { 
         if(! err) { 
           console.log('article each callback'); 
         } else { 
           callback(error); 
         } 
       }); 
     }); 
     callback(); 
} 
function parseArticle(item, callback) { 
     if(item.hasOwnProperty('rssfeed_id') && item.hasOwnProperty('guid') && item.hasOwnProperty('link') && item.hasOwnProperty('title')){ 
       connection.query('SELECT * FROM rssarticle WHERE rssfeed_id = ? AND guid = ?', [item.rssfeed_id, item.guid], function(err, rows, fields) { 
         if(rows.length == 0){ 
           connection.query('INSERT INTO rssarticle SET ?', { 
             rssfeed_id: item.rssfeed_id, 
             link: item.link, 
             title: item.title, 
             description: item.description, 
             publish_date: item.pubDate, 
             guid: item.guid 
           }, function(err, result){ 
             if(err != null){ 
               console.log(err); 
             } 
           }); 
         } 
       }); 
     } 
     callback(); 
} 
+0

オムは、あなたが何か他のものを探しているのですか? – adeneo

答えて

5

1つは、コールバックをあまりにも早く呼び出すことです。

function parseFeed(feed, callback) { 
    request 
    .streamStuff() 
    .streamStuff() 
    .streamStuff(); 

    callback(); 
} 

完了する前にcallbackに電話してはいけません。さもなければ、あなたの「終了」メソッドが呼び出されますが、あなたの非同期コードは実際にはまだ実行されています。

ので、代わりのやって:

.on('finish', function() { 
    async.eachLimit(articles, 10, parseArticle, function(err) { 
     if(! err) { 
      console.log('article each callback'); 
     } else { 
      callback(error); 
     } 
    }); 
}); 
callback(); 

をジャスト反復におけるすべての非同期操作が完了した後にコールバックが呼び出され

.on('finish', function() { 
    async.eachLimit(articles, 10, parseArticle, function(err) { 
     if(! err) { 
      // assuming this is a stub and really ends up doing `callback();` 
      console.log('article each callback'); 
     } else { 
      callback(error); 
     } 
    }); 
}); 
+0

AHA!そこに行く。コールバックを記事に関係する 'eachLimit'に移しました。すべてが修正されました。ありがとう! – tubaguy50035

+2

今後は、名前の付いた関数(匿名の関数とは対照的に)を使って作業を単純化しておくことが重要です。非同期フローがどこにつながっているのかが分かりやすくなります。 – bevacqua

+0

また、コールバックをより適切な名前にすることは本当に便利です。例えば、それらを区別するために 'next'と' done'を使いたいと思います。 – bevacqua

関連する問題