javascript - node.js async.each callback, miten tiedän, milloin se on valmis?


Yritän ymmärtää Node.js:ää ja joitakin asynkronisia operaatioita. Seuraavassa koodissa haen joitakin RSS-syötteitä ja tallennan löydetyt artikkelit, jos en ole tallentanut niitä aikaisemmin. Koodi toimii ja tallentaa uudet artikkelit. En kuitenkaan ole varma, miten muokkaisin tätä niin, että tietäisin, kun kaikki artikkelit on käsitelty. Esimerkiksi jokaisen async.eachLimit -kutsun callback kutsutaan aina, kun raja täyttyy (10 artikkelin tai 5 syötteen jälkeen). Miten siis tiedän, milloin ne ovat valmiit?

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

Vastaus #1

Ensinnäkin kutsut palautteitasi ennakkoon aivan liian aikaisin.

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

  callback();
}

Sinun ei pitäisi kutsua callback-funktiota ennen kuin olet valmis. Muuten "finished"-metodiasi kutsutaan, mutta asynkroninen koodisi on itse asiassa edelleen käynnissä.

Joten sen tekemisen sijaan:

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

Tee vain

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