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

问题背景:
我用的是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
//resultsisnowanarrayoftheresponsebodies
console.log(results)
})
这不就是我梦寐以求的吗?然而无情的现实是公司目前并不想升级nodejs,所以还是得乖乖用generator。后来我又想把上面的代码改造成generator/yield
async.mapLimit(urls,5,function*(url){
constresponse=yieldfetch(url)
returnresponse.body
},(err,results)=>{
if(err)throwerr
//resultsisnowanarrayoftheresponsebodies
console.log(results)
})
然而一个回调函数都执行不了。所以第二个问题是为啥不能直接改造呢,async不是generator的语法糖吗?
HUX布斯
浏览 756回答 2
2回答

神不在的星期二

第一个问题:co-parallel第二个问题:你需要把function*(url){}用co包一下。generator并不会自动执行,某种程度上你可以把async函数视为自动帮你co一下了的generator。但是不确定你这么写能不能执行,待会测试一下。

侃侃无极

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肯定不行了
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript