多个Node.js回调的问题

时间:2014-09-15 03:30:16

标签: javascript node.js mongodb mongoose

我试图解决我使用nodejs cronjob的问题。所以基本上,这个请求从soundcloud抓取我的轨道,我遍历结果并将数据放在mongodb集合中。这一切都很好,但现在我在网站上添加了另一个部分,所以我需要从另一个集合中获取一些额外的信息。

我有一个曲目集合和一个库存集合。轨道ID在两个集合中,以将附加轨道数据与新拉出的轨道相关联。 所以我的问题是如何才能获得这些额外的跟踪数据?下面我尝试循环使用mongoose的query.find()注入数据但是循环不起作用一起。库存查询的回调将在一个for循环中运行似乎......我不确定那里是什么。

我非常确定您也可以通过在架构中引用来从另一个集合中注入文档...但我不确定如何使其工作。这显然是一个更好的解决方案,因为它不需要更多像这样的代码。

如果有人对我有任何建议会很棒!

request({
url: url,
json: true
}, function (error, response, body) {
if (!error && response.statusCode === 200) {
        var o = 1;

        for(i=0; i < body.tracks.length; i++){
            var last = (i + 1);
            var track = body.tracks[i];

            if( track.sharing == 'public'){
                var invData;
                var obj;

                db.model('inventory').find({id:track.id}).exec(function(err,item){
                    //console.log(item[0]);
                    invData = item[0];


                });


                console.log(invData, obj);

                obj = new TracksModel({
                    id: track.id,
                    sharing:track.sharing,
                    uri:track.uri,
                    description:track.description,
                    created_at:track.created_at,
                    duration:track.duration,
                    title:track.title,
                    description:track.description,
                    order: o,
                    inventory_data: invData
                });





                o++;

                obj.save(function (err) {
                    if (!err) {
                        console.log('Track inserted successfully');
                    } else {
                        throw err;
                    }
                });

                if(last == body.length){
                    setTimeout(function(){
                        console.log("Automatically closing database connection after 5 seconds");
                        db.close();
                    }, 5000);
                }

            }

        }

} else {
    console.log('An error has occurred: ', error);
}
});

2 个答案:

答案 0 :(得分:1)

您对查询回调的处理方式是错误的。您假设代码从“console.log(invData,obj);”开始将在db.model.find之后立即执行。这不是Callback的正确概念。如何将该代码放在exec回调函数中。您可能必须使用闭包。 类似的东西:

if (!error && response.statusCode === 200) {
    var o = 1;

    for(i=0; i < body.tracks.length; i++){
        var last = (i + 1);
        var track = body.tracks[i];

        if( track.sharing == 'public'){

            (function(track,last,o){

                var invData;
                var obj;

                db.model('inventory').find({id:track.id}).exec(function(err,item){
                    //console.log(item[0]);
                    invData = item[0];

                    console.log(invData, obj);

                    obj = new TracksModel({
                        id: track.id,
                        sharing:track.sharing,
                        uri:track.uri,
                        description:track.description,
                        created_at:track.created_at,
                        duration:track.duration,
                        title:track.title,
                        description:track.description,
                        order: o,
                        inventory_data: invData
                    });

                    obj.save(function (err) {
                        if (!err) {
                            console.log('Track inserted successfully');
                        } else {
                            throw err;
                        }
                    });

                    if(last == body.length){
                        setTimeout(function(){
                            console.log("Automatically closing database connection after 5 seconds");
                            db.close();
                        }, 5000);
                    }
                });
            }(track,last,o);    

            o++;
        }

    }

}

答案 1 :(得分:0)

试试这个:

var utils = require('restberry-utils');

var Inventory = mongoose.model('Inventory');
var Track = mongoose.model('Track');

request({
    url: url,
    json: true
}, function (error, response, body) {
    if (error || response.statusCode !== 200) {
        console.log('An error has occurred: ', error);
        return;
    }
    utils.forEachAndDone(body.track, function(track, iter) {
        if (track.sharing !== 'public') {
            iter();
            return;
        }
        Inventory.findOne({ id: track.id }, function(err, item) {
            new Track({
                id: track.id,
                sharing: track.sharing,
                uri: track.uri,
                description: track.description,
                created_at: track.created_at,
                duration: track.duration,
                title: track.title,
                description: track.description,
                order: o,
                inventory_data: item,
            }).save(function(err) {
                if (err) {
                    throw err;
                } else {
                    console.log('Track inserted successfully');
                    iter();
                }
            })
        });
    }, function() {
        console.log('Done!');
        setTimeout(function() {
            console.log("Automatically closing database connection after 5 seconds");
            db.close();
        }, 5000);
    })
});