for 循环 异步 求助!!
发布于 8个月前 作者 hsh075623201 507 次浏览

根据条件查询数据库,得到一个数据集合,然后再根据数据集合进行循环查询。。形如如下格式:

users.find({userId:""},function(err,userCollection){// for(var i=0 ;i<userCollection.length;i++){ roles.find({roleId:userCollection[i].roleId},function(err,roleCollection){// for(var j =0 ;j<roleCollection.length;j++){ actions.find({actionId:roleCollection[j].actionId},function(err,actionCollection){//
redis.set(userCollection[i].id,JSON.stringify(actionCollection)) }) }
}) } } 但是 这种方式 感觉 存在问题 ,请问应该如何实现??

22 回复

樓上要實現一個什麼效果 從你的描述看,可能的問題就是執行玩循環後 循環內部的一些回調都還沒有調用

异步的循环要自己保证好状态的,这样子肯定是不行的
可以使用async之类的库

我的 目的 是要 根据 用户 查找其 用户角色 再根据用户角色 查找对应的角色权限 ,但是由于用户 角色 权限 她们之间是多对多的关系 所以需要循环查询。。最终的目的 是获取用户具有哪些权限 ,但是由于是异步处理,上述方案感觉会存在问题(没实验验证),首先请问上述方案存在 问题吗 ,其次是有更好的实现方式吗 ?

请问 都是采用同步方式获取数据吗?

@hsh075623201 这么多循环,不头大么?赶脚亲的代码有bug

@hsh075623201 还是异步的把,不过要有个状态,标记执行结束

@kingapple 我也 感觉有问题 ,所以在寻求帮助。。。

@fantasyni 我找到 你提供的async库 的方法了,现正在看。。。

我以前遇到的问题和你类似:比如有2张表,user 和 posts,从posts查询完得到一个数组之后要到user获取相应的用户信息。开始我也是像你那样写的,但是发现不行,后来我就用了node自带的 event 模块,注册事件并监听就ok了。

看看朴灵的 EventProxy 地址:https://github.com/JacksonTian/eventproxy 这个应该用异步编程的发布/订阅模式,朴灵的EventProxy很好用的,我们这个中文社区就用的EventProxy

现准备尝试async 中waterfall 方法 ,如不行再使用event模块。。。

我一开始也是想到朴灵的 EventProxy 但是从网上的资料看 ,没发现有参数传递的,请问它具有参数传递的功能吗?

这是node.js中比较著名的一个问题了,主要是异步和闭包相关的,可以这样写 users.find({userId:""},function(err,userCollection) {// for (var i = 0; i < userCollection.length; i++) { (function (idx) { roles.find({roleId: userCollection[idx].roleId}, function (err, roleCollection) {// for (var j = 0; j < roleCollection.length; j++) { actions.find({actionId: roleCollection[j].actionId}, function (err, actionCollection) {// redis.set(userCollection[idx].id, JSON.stringify(actionCollection)) }) } }) })(i); } });

用一个自执行的function把外层for循环里面的东西包起来,把i当做参数传给function,那idx其实就是i,这样的话idx的值就可以保存下来并被里面的操作正确的访问到了。否则因为异步的原因,你里面的操作每次取到i的值是最后一次i的值。理解了闭包和异步对于学习node进步会很明显,楼主加油。

楼主 你应该再学学MongoDB。 MongoDB里就有抓取对应的模型的方法。 比如 与一条用户信息(userInfo)对应有N个角色信息(roles),可以使用某个字段将两种模型关联起来,就是$ref 属性 比如 userInfo.admin={$ref:’roles’,$id:【roles集合内某文档的_id的值】}。 在查询到这条信息时,你可以使用这个属性抓取对应的role文档. 这里只是一个提示,具体的操作方法 请楼主自己搜索!

其实,本人使用的是mongoosejs在对付此类问题时就很简单。楼主可以看一下这个。 http://mongoosejs.com/docs/populate.html 如果你看了这个,楼主 你会豁然开朗。

嗯 說的對 沒有注意他最內層還有用到i 樓主都套了三層 還是用點async什麼的吧

其实 我本来也想使用此方法的,但是出现如下问题: http://cnodejs.org/topic/538568fea087f45620d07847 由于是初学者,实在找不到原因,所以就放弃了。。。望解答,万分感谢!!

@jiangzhuo 现使用async 如下所示 但感觉仍不是 很好,请指教。 async.waterfall([ function(callback){ Users.findOne({userId:user.userId},function(err,userCollection){

                        callback(null, userCollection.roleId);
                    });

                },
                function(RoleIdCol, callback){
                    var count = RoleIdCol.length;
                    if(RoleIdCol == undefined||RoleIdCol.length==0){
                        callback(null, "");
                    }
                    for(var i =0 ;i<RoleIdCol.length;i++){
                        Role.findOne({roleId:RoleIdCol[i]},function(err,roleCollection){
                            if(roleCollection.actionId.length!=0){
                                arrayRole.push(roleCollection.actionId);
                            }else{
                                count--;
                            }
                            if(arrayRole.length ==count){
                                callback(null, arrayRole);
                            }
                        })
                    }
                }
            ], function (err, result) {
                //result保存的都是权限Id 

            });

由于是初学者,对于闭包还不怎么了理解,正在学习中,感谢提供解决方案!

var userCollection = yield users.find({userId:""})
for(var i=0 ;i<userCollection.length;i++){
    var roleCollection = yield roles.find({roleId:userCollection[i].roleId});
    for(var j =0 ;j<roleCollection.length;j++){
        var actionCollection = yield actions.find({actionId:roleCollection[j].actionId});
        redis.set(userCollection[i].id,JSON.stringify(actionCollection))
    }
}

学习了,第一次看到使用yield的方式。。。

也可以试试 promise,也可以把移步调用的部分抽离出来放到独立的 function 里面,确保回调执行时外部闭包的状态是正确的

回到顶部