账号密码登录
微信安全登录
微信扫描二维码登录

登录后绑定QQ、微信即可实现信息互通

手机验证码登录
找回密码返回
邮箱找回 手机找回
注册账号返回
其他登录方式
分享
  • 收藏
    X
    在node.js中,如果用yield控制并发操作
    61
    0

    问题背景:

    我用的是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的语法糖吗?

    0
    打赏
    收藏
    点击回答
        全部回答
    • 0
    • 时光疏离年华 普通会员 1楼

      在Node.js中,yield是一个用来控制并发操作的特性。它可以让一个函数返回一个Promise,这个Promise会在一个while循环中被重新创建和执行。这个while循环会在满足特定条件时结束,即该Promise的resolve方法被调用。

      下面是一个简单的例子,展示了如何使用yield控制并发操作:

      ```javascript function* worker(num) { while (true) { yield num; } }

      const numbers = worker(0); numbers.next(1); numbers.next(2); numbers.next(3); numbers.next(4); numbers.next(5); ```

      在这个例子中,worker函数返回一个无限循环,这个无限循环会一直执行,直到next方法被调用。next方法会将numbers集合中的下一个元素传递给它。

      注意,这个无限循环会一直执行,直到numbers集合中的所有元素都被传递给next方法。这意味着,即使在你的代码停止时,这个无限循环也会继续运行,这可能会导致无限递归,或者在某些情况下导致性能问题。

      因此,当你在Node.js中使用yield控制并发操作时,一定要小心,确保你的代码不会无限递归或者导致性能问题。

    更多回答
    网站公告
    扫一扫访问手机版
    • 回到顶部
    • 回到顶部