为了账号安全,请及时绑定邮箱和手机立即绑定

在node.js中,如果用yield控制并发操作

在node.js中,如果用yield控制并发操作

HUX布斯 2019-05-23 19:20:11
问题背景:我用的是egg1.x,基于koa。然后就是各种generator,各种yield调用。这样的好处是编码舒服,都是同步代码。缺点是在某些情况下,速度会异常缓慢。比如有些逻辑需要基于http协议循环调用另外的服务。egg官网上提供了一种基于yield的控制并发方法,代码如下:const[news,user]=yield[ctx.service.news.list(topic),ctx.service.user.get(uid),];这是一种极度简单的使用场景。它无法控制并发量。所以我把它改造成了如下代码:constconcurrency=5;letindex=0;lettempArr=[];for(constitemofdata){tempArr.push(ctx.service.user.get(item.uid));if(index===concurrency){yieldtempArr;tempArr=[];index=0;}index++;}if(tempArr.length){yieldtempArr;}这样写确实可以达到效果,当然如果需要处理返回值,会更复杂一点。但是本人水平有限,想不出什么办法将这个方法进行封装。所以想问的第一个问题便是如何封装它。async的maplimit在async的文档上找到如下代码async.mapLimit(urls,5,asyncfunction(url){constresponse=awaitfetch(url)returnresponse.body},(err,results)=>{if(err)throwerr//resultsisnowanarrayoftheresponsebodiesconsole.log(results)})这不就是我梦寐以求的吗?然而无情的现实是公司目前并不想升级nodejs,所以还是得乖乖用generator。后来我又想把上面的代码改造成generator/yieldasync.mapLimit(urls,5,function*(url){constresponse=yieldfetch(url)returnresponse.body},(err,results)=>{if(err)throwerr//resultsisnowanarrayoftheresponsebodiesconsole.log(results)})然而一个回调函数都执行不了。所以第二个问题是为啥不能直接改造呢,async不是generator的语法糖吗?
查看完整描述

2 回答

?
神不在的星期二

TA贡献1963条经验 获得超6个赞

第一个问题:co-parallel
第二个问题:你需要把function*(url){}用co包一下。generator并不会自动执行,某种程度上你可以把async函数视为自动帮你co一下了的generator。但是不确定你这么写能不能执行,待会测试一下。
                            
查看完整回答
反对 回复 2019-05-23
?
侃侃无极

TA贡献2051条经验 获得超10个赞

constco=require('co');
functionmapLimit(urls,limit,genFn,cb){
co(function*(){
letresults=[];
while(urls.length){
letres=yieldurls.splice(0,limit).map(genFn);
results.push(...res);
}
returnresults;
}).then(function(res){
cb(null,res)
}).catch(cb)
}
这样封装楼主看看能吗async.mapLimit官方文档里要求传asyncFUnction函数,传Generator肯定不行了
                            
查看完整回答
反对 回复 2019-05-23
  • 2 回答
  • 0 关注
  • 755 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信