问题背景:我用的是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。但是不确定你这么写能不能执行,待会测试一下。
侃侃无极
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肯定不行了
添加回答
举报
0/150
提交
取消