json - 多个异步 mongo 请求生成困惑的返回

标签 json node.js mongodb asynchronous async.js

我正在尝试根据 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 时,由于 header 已经发送,它会严重崩溃。

现在如您所见,我有 3 个系列:用户源、服装和商店。 此函数的目标是检索 userfeed 集合中的所有项目,提取服装(基于 userfeed 集合一部分的outfit_id 数组),并以相同的方式提取与每个 userfeed 条目相关的商店信息,如下所示:

enter image description here

我知道 async.js 或类似的东西是可行的方法:我已经像 SO 上的无数其他帖子一样红了,但我仍然无法理解它,可能是因为 async.js 或流程控制背后的整个机制总体上仍然在我的脑海中失去焦点。 我仍然是 Node 菜鸟:)

更新

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

这个人在逐个用例地描述将 async.js 应用于代码的所有方法方面做得非常出色。 一旦我解决了这个问题,我就会发布解决方案。

更新2

感谢上面的人,我可以找到一个可行的解决方案,下面是答案。

最佳答案

经过一番努力,我终于找到了解决方案。 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);
    });
};

关于json - 多个异步 mongo 请求生成困惑的返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19404827/

相关文章:

javascript - 将数据作为对象传递给 mongoDb,将其用作查询和比较

json - JSON 文件中的 Ansible 变量替换问题

node.js - Express js可选参数

java - 将 Web 请求的字符串转换为 JSON 数组

node.js - Sequelize 获取最近的位置获取点

node.js - 脚本在 Webstorm 中失败,但不是来自终端

c# - 如何更新mongo db中的所有记录#

node.js - 从不同的地理位置访问快速服务器

json - 如何在flutter中将Json解码为DateTime格式?

java - jackson 处理接口(interface)