• 请不要在回答技术问题时复制粘贴 AI 生成的内容
lolizeppelin
V2EX  ›  程序员

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

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

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

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

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

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

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

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

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

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

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

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