最近项目里有个问题一直困扰了我挺久的,需要在循环里去查找数据库,把查询到的数据push到一个数组里,并且在循环完成后才返还,现在我想到的是在循环里面加入了个立即执行函数,将循环变量传入立即执行函数,除此之外还有其他好的写法吗?,还有我如何知道这个循环什么时候完成了呢? 伪代码: var results; for(var i=0;i<docs.length;i++){ (function(i){ db.findOne({_id : docs[i]._id},function(err,collection){ results.push(collection); }) }){i} } res.end(JSON.stringify(results)); //[] 希望有大大给我解决下困惑,非常感谢
请使用异步流程控制库:async,peomise 等
来自酷炫的 CNodeMD
把数据库操作放进循环通常不是好办法,是不是异步和这没有关系。更优雅的实现是一次性把ID序列传进一词数据库操作,如果能findOne,自然应该有findMany。
@o6875461 现在项目里有用到,但是还是不能很好解决问题呢
@flamingtop 嗯嗯,是我的思路存在问题,要回去重构代码了,非常感谢你的回答
@weapon-xx 笑了,请查看async.map方法,或promise的map方法,如果还无法解决,请无视
来自酷炫的 CNodeMD
使用闭包方法,能够解决循环里的异步问题
使用Promise吧
function promise(id) {
return new Promise(function (reslove, reject) {
db.findOne({_id: id._id}, function (err, collection) {
if (err) {
return reject(err);
}
resolve(collection);
});
});
}
let arr = docs.map(item=>promise(docs[item]));
Promise.all(arr).then(results=>res.end(JSON.stringify(results))).catch(err=>console.error(err));
或者用Generator函数,更加接近常用的逻辑
function _gen(req, res, next) {
let results = [];
for (let i = 0; i < docs.length; i++) {
let resTmp = yield promiseFindOne(docs[i]._id);
results.push(resTmp);
}
res.end(JSON.stringify(results));
}
app.get('/', function (req, res, next) {
require('co')(_gen, req, res, next).catch(err=>next(err));
});
@hyj1991 赞,学习了:)
@liuxufei 感谢,用eventproxy实现,代码好看多了
最好的方式,后期扩展维护最好的应该是 co.js