在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),
];
这是一种极度简单的使用场景。它无法控制并发量。所以我把它改造成了如下代码:
const concurrency = 5;
let index = 0;
let tempArr = [];
for (const item of data) {
tempArr.push(ctx.service.user.get(item.uid));
if (index === concurrency) {
yield tempArr;
tempArr = [];
index = 0;
}
index++;
}
if (tempArr.length) {
yield tempArr;
}
这样写确实可以达到效果,当然如果需要处理返回值,会更复杂一点。但是本人水平有限,想不出什么办法将这个方法进行封装。所以想问的第一个问题便是如何封装它。
async的maplimit
在async的文档上找到如下代码
async.mapLimit(urls, 5, async function(url) {
const response = await fetch(url)
return response.body
}, (err, results) => {
if (err) throw err
// results is now an array of the response bodies
console.log(results)
})
这不就是我梦寐以求的吗?然而无情的现实是公司目前并不想升级nodejs,所以还是得乖乖用generator。后来我又想把上面的代码改造成generator/yield
async.mapLimit(urls, 5, function* (url) {
const response = yield fetch(url)
return response.body
}, (err, results) => {
if (err) throw err
// results is now an array of the response bodies
console.log(results)
})
然而一个回调函数都执行不了。所以第二个问题是为啥不能直接改造呢,async不是generator的语法糖吗?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
第一个问题:
co-parallel
第二个问题:
你需要把 function*(url){} 用 co 包一下。generator 并不会自动执行,某种程度上你可以把 async 函数视为自动帮你 co 一下了的 generator。
但是不确定你这么写能不能执行,待会测试一下。
这样封装楼主看看能吗
async.mapLimit官方文档里要求传asyncFUnction函数,传Generator肯定不行了
async是generator的语法糖,但不是简单的替换就可以解决的
使用await语法自带执行器,而generator则是不带执行器,需要自己手工添加
await需要后面的变量是一个promise对象
给你个generator+promise对 async/await的实现