需要节点 for-loop 回调
Node for-loop callback required
我想更改从其中一个集合中获取的 Tags 格式。 Tags 数据包含数组中的一些 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));
但我没有得到想要的结果。响应以 Tag 初始形式而不是格式化形式给出数据。我想这是由于事件循环。如果有人能帮助我,我将不胜感激。
**编辑:**我使用 MongoDB 作为数据库,使用 mongoose 作为 ORM。
您可以使用 promises 或 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
});
P.S。也许,代码包含错误。我无法测试它。
我建议使用 promises 来管理你的异步操作,它现在是 ES6 中的标准。你没有说你正在使用什么数据库(它可能已经有一个基于承诺的接口)。如果没有,那么我们手动承诺 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
});
我想更改从其中一个集合中获取的 Tags 格式。 Tags 数据包含数组中的一些 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));
但我没有得到想要的结果。响应以 Tag 初始形式而不是格式化形式给出数据。我想这是由于事件循环。如果有人能帮助我,我将不胜感激。
**编辑:**我使用 MongoDB 作为数据库,使用 mongoose 作为 ORM。
您可以使用 promises 或 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
});
P.S。也许,代码包含错误。我无法测试它。
我建议使用 promises 来管理你的异步操作,它现在是 ES6 中的标准。你没有说你正在使用什么数据库(它可能已经有一个基于承诺的接口)。如果没有,那么我们手动承诺 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
});