V2EX = way to explore
V2EX 是一个关于分享和探索的地方
Sign Up Now
For Existing Member  Sign In
• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lolizeppelin
V2EX  ›  程序员

Promise 中如何 sleep(不是实现 sleep)

  •  
  •   lolizeppelin · Jun 27, 2018 · 4775 views
    This topic created in 2866 days ago, the information mentioned may be changed or developed.

    我的函数原型如下

    
    const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
    
    
    class GversionsBulkUpdate extends React.Component {
    
      ......
    
      update = async () => {
        const { handleLoadingClose, handleLoading, appStore } = this.props;
        handleLoading();
    
        let bulkMax = 10;   // 最大并发值
        const fails = [];
    
        await new Promise((resolve) => {
          const isFinish = finish(this.state.list.length, resolve);                  // finish mark
          this.state.list.forEach((pkginfo) => {
            while (bulkMax <= 0) await sleep(300); // 限制并发数量
            bulkMax -= 1;
            const body = { address: pkginfo.url, gversion: pkginfo.gversion, ftype: pkginfo.ftype };
            goGameRequest.createPfile(appStore.user, pkginfo.pkg.package_id, body,
              () => { console.log('finish one'); bulkMax += 1; isFinish.next(); },  // error callback
              (msg) => {                                                            // success callback
                console.log(msg);
                bulkMax += 1;
                isFinish.next();
                fails.push({ pkg: pkginfo.pkg, msg });
              });
          });
        });
        console.log(fails)
        const msg = fails.length === 0 ? '批量更新执行完毕' : '部分包更新失败';
        handleLoadingClose(msg);
        this.setState({ parameters: Object.assign({}, BaseParameters),
          list: Object.assign([], baseList),
          packages: Object.assign([], this.pacakges) });
      };
      
      ......
    

    createPfile 是个 http 请求

    想用 while (bulkMax <= 0) await sleep(300); 限制并发请求数量

    但是语法错误....Promise 中需要等待要如何写..有点懵比了

    20 replies    2018-06-28 01:08:34 +08:00
    coderfox
        2
    coderfox  
       Jun 27, 2018 via Android
    删掉 await new Promise 的包装。
    因为 new Promise 那里接受一个闭包参数,闭包函数不是 async,所以不能在其中使用 await。
    没有必要在 async 函数中还手动构造 Promise 然后 await 掉。
    建议重新学学 Promise。
    lolizeppelin
        3
    lolizeppelin  
    OP
       Jun 27, 2018
    await new Promise 是为了等待这个 Promise 结束以后才调用 handleLoadingClose, 故意那样写的谢谢
    lolizeppelin
        4
    lolizeppelin  
    OP
       Jun 27, 2018
    hahastudio
        5
    hahastudio  
       Jun 27, 2018
    https://stackoverflow.com/questions/951021/what-is-the-javascript-version-of-sleep
    function sleep(ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
    }
    hahastudio
        6
    hahastudio  
       Jun 27, 2018
    主要是不是丢给 promise 的函数没有 async 啊
    orzfly
        7
    orzfly  
       Jun 27, 2018 via Android
    唉,你的 forEach 后的函数没有带 async 修饰字,而且 forEach 也不支持 Promise,所以不能用 await。你可以用原生的 for 循环代替 forEach,或者用 Bluebird.map 等函数代替 forEach。
    orzfly
        8
    orzfly  
       Jun 27, 2018 via Android
    所以,限制并发的话,也可以试试 Bluebird.map(..., ..., { concurrency: 5 })。
    lolizeppelin
        9
    lolizeppelin  
    OP
       Jun 27, 2018
    @sethverlo
    谢谢...但这个也不好用 我想要能阻塞住 this.state.list.forEach((pkginfo)

    delay 的实现不了啊.....

    如果不行的话我只能写个大循环, 每次先先判断是否到并发上限....到上限就延迟...没到上限就扫描 this.state.list

    每次还要把已经完成的从 this.state.list 移出去....写起来忒难看
    lolizeppelin
        10
    lolizeppelin  
    OP
       Jun 27, 2018
    @orzfly

    可以了....谢谢你的提醒 要的就是这个效果

    this.state.list.forEach(async (pkginfo)

    就可以了!!!! 3q
    lovedebug
        11
    lovedebug  
       Jun 27, 2018
    this.state.list.forEach 最好换成 await Promise.all(this.state.list.map(async (pkginfo) =>{})
    既然你限制并发数,还用 forEach,每次取 10 个做不好吗?多余的 return,等待达成进入条件
    lolizeppelin
        12
    lolizeppelin  
    OP
       Jun 27, 2018
    @lovedebug

    不能等 10 个完成...再下一批 10 个....

    要做到完成一个 下一个立刻上....

    用 sleep 已经算偷懒写法了..... 正确的写法应该是完成的直接 yeid 过去...js 我没那么熟悉 sleep 解决就算了
    lovedebug
        13
    lovedebug  
       Jun 27, 2018
    考虑 node 的库吧。或者自己内部写个定时器。周期性检测是否可以执行。
    lovedebug
        14
    lovedebug  
       Jun 27, 2018
    如果单纯要连续做任务,换成队列不断的取就可以。类似 Java 线程池。
    momocraft
        15
    momocraft  
       Jun 27, 2018
    你需要 delay 的其实是开始而不是结束,Promise 对象生成时那个任务已经开始了,再想想吧。
    famiko
        16
    famiko  
       Jun 27, 2018
    限制并发。。Promise.race 了解一下
    jimliang
        17
    jimliang  
       Jun 27, 2018
    bluebird 的 Promise 支持修改并发数
    http://bluebirdjs.com/docs/api/promise.map.html
    ```
    ...map(..., {concurrency: 3});
    ```
    lolizeppelin
        18
    lolizeppelin  
    OP
       Jun 27, 2018
    @momocraft
    并不是 delay 完就能执行啊.....delay 完我还要判断是否达到上限,还是在上限还得 delay 啊.....

    @jimliang
    谢谢提供新的解决方法....不过这边已经解决了就不引入更多的库了
    jimliang
        19
    jimliang  
       Jun 27, 2018
    @lolizeppelin 不一定要引库,只是作为参考自己写一个并发控制的逻辑
    wangjie
        20
    wangjie  
       Jun 28, 2018 via Android
    @lolizeppelin #3 2l 就指出了你的语法错误所在你还没有意识到 XD
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Solana   ·   2547 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 06:08 · PVG 14:08 · LAX 23:08 · JFK 02:08
    ♥ Do have faith in what you're doing.