2013-12-10 3 views
6

Я пытаюсь обернуть голову вокруг Node.js и некоторые асинхронные операции. В следующем коде я получаю некоторые RSS-каналы и сохраняю найденные статьи, если я их ранее не сохранял. Код работает и хранит новые статьи. Тем не менее, я не уверен, как изменить это, чтобы я знал, когда все статьи будут обработаны. Например, обратный вызов по каждому async.eachLimit вызывается каждый раз, когда предел выполняется (после 10 статей или 5 каналов). Итак, как я узнаю, когда они закончили?node.js async.each callback, откуда я узнаю, когда это будет сделано?

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

Во-первых, вы предварительно вызываете свои обратные вызовы слишком рано.

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

Смежные вопросы