【问题标题】:multiple async mongo request generate messed up returns多个异步 mongo 请求生成混乱的返回
【发布时间】:2014-07-01 22:38:30
【问题描述】:

我正在尝试从我的 mongodb 上的多个请求中构建一个 JSON。 因为我没有使用 DBRef,所以我必须自己构建“表关节”,这就是我最终陷入困境的原因。 这是几天以来让我头疼的代码。 (mongo部分是用mongoskin完成的)

        var getUserFeed = function(thelimit, out) {
          userfeed = db.collection("userfeed");
          apparel = db.collection("apparel");
          store = db.collection("stores");
          if(thelimit)
            args = {limit:thelimit, sort: [['date',-1]]};

          userfeed.find({},args).toArray(function(e, feed) {
            if (e) console.log("error: ", e);
            // gather aparel infos
            var i=0;
            var ret_feeds = [];
            feed.forEach(function(cur_feed) {
                var outfits=[];
                console.log("beginning with: " + cur_feed.url);
                var resfeed = "";
                resfeed = cur_feed;
                resfeed.url = baseurl + snapurl + resfeed.url + "_small.jpg";
                i=0;
                cur_feed.apparel_ids.forEach(function(item) {
            /*>>*/  apparel.find({"_id": item},{limit:1}).toArray(function(e, results) {
                        console.log(">>>>>>>>>>> APPAREL_FIND { i:" + i + "}");
                        if (e) console.log("error: ", e);
                        results = results[0];
                        if(results.apparel_cat == 1)
                            url_subcat = "pants/";
                        else if(results.apparel_cat == 2)
                            url_subcat = "shirts/";
                        else if(results.apparel_cat == 2)
                            url_subcat = "tshirts/";

                        results.thumb = baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg";
                        results.size = "M"; ///// TOBE REAL VERY SOON
                        results.gallery = [
                            baseurl + outfiturl + url_subcat + results.apparel_id + "/model.jpg",
                            baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg"
                        ];
                        outfits.push(results); // quick and dirty, 2 b refined..
                        i++;
                        if(i>=cur_feed.apparel_ids.length)
                        {
                            // pack it up
        //                  resfeed.url = resfeed.url;
                            resfeed.outfits = outfits;
                            resfeed.fav = false;
                            resfeed.bough = false;

                            // retrieve store infos
                /*>>>*/     store.find({"_id":resfeed.store_id}, {limit: 1}).toArray(function(e, resstore) {
                                console.log("\t############# STORE_FIND { i:" + i + "}");
                                if (e) console.log("error: ", e);
                                resfeed.store = resstore[0];
                                resfeed.store.class = "hem";
                                ret_feeds.push(resfeed);
                                if(ret_feeds.length >= feed.length)
                                {
                                    console.log("\t\t@@@@@@@@@@@@@@@@@@@@@@calling return [ ret_feeds.length = " + ret_feeds.length + " feed.length = " + feed.length);
                                    out.send(ret_feeds);
                                }
                            });
                        }
                  });
                });
            });
          });
        }

此代码失败,因为在完成任务之前返回了 json,所以下次它尝试返回另一个 json 时,由于标头已经发送,它会惨遭崩溃。

现在您可以看到,我有 3 个集合:用户源、服装和商店。 此函数的目标是检索 userfeed 集合中的所有项目,提取服装(基于作为 userfeed 集合的一部分的 suit_id 数组),并以相同的方式提取与每个 userfeed 条目相关的商店信息,像这样:

我知道 async.js 或等效的方法是要走的路:我已经像 SO 上的无数其他帖子一样红了,但我仍然无法理解它,可能是因为背后的整个机制async.js 或一般的流控制在我的脑海中仍然没有重点。 我仍然是节点的菜鸟:)

更新

我想我在这里找到了正确的理解途径:http://www.sebastianseilund.com/nodejs-async-in-practice

这个人在逐个用例描述将 async.js 应用到您的代码的所有方法方面做得非常出色。 我会尽快发布解决方案。

更新 2

多亏了上面的家伙,我可以找到一个可行的解决方案,下面是答案。

【问题讨论】:

    标签: json node.js mongodb asynchronous async.js


    【解决方案1】:

    经过这么多的努力,我终于设法找到了解决方案。 async.js 是我(显然)怀疑的答案。

    仅供参考,这是工作代码。 如果您想指出改进或其他任何内容,非常欢迎您

    var getUserFeed = function(thelimit, out) {
    userfeed = db.collection("userfeed");
    apparel = db.collection("apparel");
    store = db.collection("stores");
    var args;
    if(thelimit)
        args = {limit:thelimit, sort: [['date',-1]]};
    
    var outfits=[];
    var feeds = array();
    
    async.series([
        // userfeed find
        function(callback) {
            userfeed.find({},args).toArray(function(e, feed) {
                if(e) callback(e);
                feeds = array(feed);
                console.log(feeds.length + " retrieved. stepping in");
                callback(null, null);
            });
        },
    
        // join
        function(callback) {
            async.forEach(feeds, function(thefeed, callback) {
                var i = feeds.indexOf(thefeed);
                async.parallel([
                    // load apparel infos
                    function(callback) {
                        console.log("\t >>> analyzing thefeed id " + thefeed._id);
                        async.forEach(thefeed.apparel_ids, function(apparel_id, callback) {
                            apparel.find({"_id": apparel_id},{limit:1}).toArray(function(e, results) {
                                if (e) console.log("error: ", e);
                                results = results[0];
                                if(results.apparel_cat == 1)
                                    url_subcat = "pants/";
                                else if(results.apparel_cat == 2)
                                    url_subcat = "shirts/";
                                else if(results.apparel_cat == 2)
                                    url_subcat = "tshirts/";
    
                                results.thumb = baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg";
                                results.size = "M"; ///// TOBE REAL VERY SOON
                                results.gallery = [
                                    baseurl + outfiturl + url_subcat + results.apparel_id + "/model.jpg",
                                    baseurl + outfiturl + url_subcat + results.apparel_id + "/front.jpg"
                                ];
                                console.log("\t\t### pushing data into thefeed_index: " + i);
                                if(!util.isArray(feeds[i].oufits)) feeds[i].outfits = array();
                                feeds[i].outfits.push(results);
                                callback(null, null);
                            });
                        }, callback);
                    },
                    // load store infos
                    function(callback) {
                        store.find({"_id":thefeed.store_id}, {limit: 1}).toArray(function(e, resstore) {
                            console.log("\t### STORE_FIND");
                            if (e) console.log("error: ", e);
                            feeds[i].store = resstore[0];
                            feeds[i].store.class = "hem";
                            callback(null, null);
                        });
                    }
                ], callback);
            }, callback);
        }
    
        // MAIN
        ], function(err, result) {
            console.log("feed retrieval completed. stepping out");
            if (err) return next(err);
            out.send(feeds);
        });
    };
    

    【讨论】:

      猜你喜欢
      • 2013-05-15
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      • 2015-04-07
      • 1970-01-01
      • 1970-01-01
      • 2015-01-17
      • 2019-10-24
      相关资源
      最近更新 更多