2016-07-24 43 views
0

我想更改标签格式,我从其中一个集合中获取。 标签数据包含在阵列中的一些KC IDS里面我是用得到KC数据和TagUnit插入得到最终响应的格式。节点for循环回调所需

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

但我没有得到期望的结果。响应发出标签数据在初始而不是格式化的形式。我想这是由于事件循环。如果有人能帮助我,我将不胜感激。

**编辑:**我使用MongoDB作为数据库和猫鼬作为ORM。

+1

你看过[promise](http://www.html5rocks.com/en/tutorials/es6/promises/?redirect_from_locale=de)吗?你说得对,你的问题是由事件循环引起的。当调用'response.send'时,'newTags'不会被最完全计算。 – markusthoemmes

回答

1

我会建议使用承诺来管理你现在是ES6标准的异步操作。你不会说你正在使用什么数据库(它可能已经有一个基于承诺的界面)。如果没有,那么我们手动promisify KC.findById()

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

然后,假设你可以做所有这些发现并行操作,您可以使用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 
}); 
+0

我正在测试解决方案。同时仅供参考,我的数据库是mongoDB,ORM是猫鼬。 – Rusty

+0

@Rusty - 我有点难以告诉你想要什么样的最终结果。这段代码给了你一个对象数组数组,每个对象包含'kc_id'和'kc_title',因为这就是我认为你的原始代码试图生成的东西。 – jfriend00

+0

我希望**响应**以以下格式进行。 '{“tag_id”:“nienemk29290hu38”,“kcs”:{“kc_id”:“nmdkwmswmwjm4944”,“kc_title”:“ABC”}'。你的解决方案似乎几乎接近我正在做最后的格式化有点困难。 – Rusty

1

您可以使用承诺或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 
}); 

附:也许,代码包含错误。我无法测试它。