简体   繁体   English

需要节点for循环回调

[英]Node for-loop callback required

I want to change the Tags format which I am fetching form one of the collections. 我想更改我从收藏夹之一中获取的标签格式。 Tags data contains some KC ids in an array which I am using to get KC data and insert in TagUnit to get final response format. 标签数据在数组中包含一些KC ID,我正在使用该数组获取KC数据并插入TagUnit中以获取最终响应格式。

var newTags = Tags.map(function(TagUnit) {
    for (var i = 0; i < TagUnit.kcs.length; i++) {
        KCArray = [];
        KC.findById(TagUnit.kcs[i], function(error, data) {
            KCMap = {};
            KCMap['kc_id'] = data._id;
            KCMap['kc_title'] = data.title;
            KCArray.push(KCMap);
            if (KCArray.length == TagUnit.kcs.length) {
                TagUnit.kcs = KCArray;
            }
        });
     }
     return TagUnit;
});

response.send(JSON.stringify(newTags));

But I am not getting desired result. 但是我没有得到期望的结果。 Response is giving out Tag data in initial for instead of formatted form. 响应是以初始形式而不是格式化形式发出标签数据。 I guess it is due to event looping. 我猜这是由于事件循环造成的。 I will be grateful if someone can help me with this. 如果有人可以帮助我,我将不胜感激。

**Edit: ** I am using MongoDB as database and mongoose as ORM. **编辑:**我使用MongoDB作为数据库,使用Mongoose作为ORM。

You can use promises or Async module 您可以使用Promise或Async模块

var async = require('async');
...
function getKC (kc, callback) {
   KC.findById(kc, function(err, data) {
       if (err)
          return callback(err);

       callback(null, {kc_id: data._id, kc_title: data.title})
   });
}

function getKCs (tag, callback) {
   async.map(tag.kcs, getKC, callback);
}

async.map(Tags, getKCs, function(err, results){
    if (err)
       return console.log(err.message);

    res.json(results); // or modify and send
});

PS Perhaps, code contains errors. PS也许,代码包含错误。 I cann't test it. 我无法测试。

I'd suggest using promises to manage your async operations which is now the standard in ES6. 我建议使用诺言来管理您的异步操作,这现在已成为ES6中的标准。 You don't say what database you're using (it may already have a promise-based interface). 您没有说您正在使用什么数据库(它可能已经具有基于Promise的界面)。 If it doesn't, then we manually promisify KC.findById() : 如果不是,那么我们手动启用KC.findById()

function findById(key) {
    return new Promise(function(resolve, reject) {
        KC.findById(key, function(err, data) {
            if (err) return reject(err);
            resolve(data);
        });
    });
}

Then, assuming you can do all these find operations in parallel, you can use Promise.all() to both keep track of when they are all done and to order them for you. 然后,假设您可以并行执行所有这些查找操作,则可以使用Promise.all()跟踪完成的时间并为您排序。

var allPromises = Tags.map(function(TagUnit) {
    var promises = TagUnit.kcs.map(function(key) {
        return findById(key).then(function(data) {
            // make resolved value be this object
            return {kc_id: data._id, kc_title: data.title};
        });
    });
    // this returns a promise that resolves with an array of the kc_id and kc_title objects
    return Promise.all(promises).then(function(results) {
        return {
             _id: TagUnit._id,
             kcs: results
        };
    });
});

// now see when they are all done
Promise.all(allPromises).then(function(results) {
    response.send(JSON.stringify(results));
}).catch(function(err) {
    // send error response here
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM