请问有没有异步改同步的库能处理类似ForEach的情况?
发布于 12 年前 作者 shinka 10419 次浏览 最后一次编辑是 8 年前

这个情况比较恶心,比如forEach() 然后这个里面每个Item都执行一个异步调用的函数,比如请求数据库查询结果,我希望在forEach之后的代码块能在上面每个Item的异步函数执行完之后再执行,请问有没有这样的库或者其他替代方案?

也就是先解决forEach的异步问题改成同步,然后forEach里面每个item的异步问题也改成同步,然后再执行forEach后面的代码块。不知道有没有描述清楚,我用过async那个库,看似能解决问题但是尝试了一下不好用…

16 回复

Node异步查数据库是并发执行,效率高很多,为什么要同步啊? 你可以搞一个计数,全部item执行完了再触发后面的代码事件(函数)就可以啦。 不知道我理解有没有错。

额… 我照着官网的API写了一个 但是不好使…

老赵的wind.js有异步改同步的功能,你查看下,我记得是有可以应用在for和forEach中的功能

@saighost 哦哦 谢谢啊 才上CNODE 公司出去秋游了 我会仔细研究一下你的代码的 非常感谢

好的 wind,js就听说了一下没看过 去看看他的forEach吧 谢啦

恩 看这个库了 可惜自己写了个例子失败了…

组长过来跟我讨论要改同步的问题 他也说到计数的方式了 但是觉得代码写得太丑不想那么做…

@saighost 这是我测试用的代码,我希望的效果是当forEach里面的异步函数都执行完毕后执行最后一个console.log,实际的结果是先执行完三个forEach,然后执行最下面那一行console.log,然后执行三个at的console,然后执行三个save的console。希望能在forEach,at,save都执行完事之后再执行最后的console.log <pre> var ids = [“50514054705efe0823000008”, “505140e060b550402400000c”, “505c092e54f35e414c000008”]; async.forEach(ids, function(item){ console.log(“forEach and id:”+item); user.at(item, function(err, u){ console.log(“at and id:”+item); u.uid = “测试用”; u.save(function(err, u2){ console.log(“save and id:”+item); }); }); }); console.log(“after async.forEach”);

@saighost 嗯 谢谢哈 昨天已经解决了 不过遇到一个新的问题 请问我用mongoose的话,想用where a_ids in aArray 或者 b_ids in bArray 或者c_ids in cArray,我刚用$where试了下失败了,代码如下,希望帮忙看看怎么整比较好。

var line = "";

if(uids_.length > 0){ line += “createby.uid in [” + uids_ + “]”; } if(gids_.length > 0){ line += " || createby.gid in [" + gids_ + “]”; } if(tids_.length > 0){ line += " || createby.tid in [" + tids_ + “]”; }

message.find({}).$where(line).setOptions(optionObj).exec(function(err, messages){ callback_(err, messages); });

https://github.com/xinyu198736/queue_do 专门处理forEach列表里的异步转同步问题。

衍生项目(使用了queue_do的模块):

同步遍历文件夹:https://github.com/xinyu198736/walk_do

自动依赖分析器:https://github.com/xinyu198736/dependparser

ok 谢谢啊~

@saighost 老哥 我有个关于async的疑问 今天用你上面的例子试了一下,发现如下问题,先贴上代码

<pre> async.forEach(msgs, function(msg, cb){ async.parallel({ group: function(callback){ if(msg.createby.gid){ group.at(msg.createby.gid, function(err, g){ callback(err, g); }); }else{ callback(null); } }, user: function(callback){ if(msg.createby.uid){ user.at(msg.createby.uid, function(err, u){ callback(err, u); }); }else{ callback(null); } }, }, function(err, r){ if(r.group){ msg[“group”] = r.group; } if(r.user){ msg[“user”] = r.user; } cb(msg); }); }, function(arg1, arg2, arg3, arg4, arg5){ 1; }); </pre> 在对msgs这个数组forEach的时候,会每次调用回调,然后回调里面取得这条message的创建者以及所在群的对象信息添加到msg属性中。但是最后一个callback是在第一个item执行完之后就调用了,由cb(msg)这句调用了,然后forEach继续执行其他的item,最后那个回调就不再执行了。我以为最后一个回调是forEach所有元素都遍历结束后才调用的。请问如果用async这个模块的话,有没有解决方法。不用计数啥的。

@saighost 嗯嗯 我一开始第一个参数也是err,后来发现不行就把err删了也没成功 复制代码的时候忘记恢复回去了 刚跟老大讨论了一下 决定用async的forEachSeries了 谢谢老哥的意见哈~

@saighost 恩恩 我改用forEachSeries了 满足需求了 呼呼 一天居然就写了一个纠结的函数…

回到顶部