代码之家  ›  专栏  ›  技术社区  ›  phoebus

JavaScript/TypeScript-承诺循环不会等待

  •  3
  • phoebus  · 技术社区  · 8 年前

    我有100个承诺。我想同时处理其中的10个,然后打印一条语句,然后并行处理下10个。然而,它并不是等待每10个承诺都能完成。

    const promises = [];
    for (let i = 1; i <= 100; i ++) {
    
       const blockPromise = this.web3.eth.getBlock(i).then((block: any) => {
            winston.info("Processing block " + i);
       }).catch((err: Error) => {
            winston.error(err);
       });
    
       promises.push(blockPromise);
    
       if (i % 10 === 0) {
           Promise.all(promises).then(() => {
                winston.info("+++ Processed " + 10 + " blocks");
           }).catch((err: Error) => {
                winston.error(err);
           });
       }
    

    我的期望是:

    Processing block 1
    Processing block 3
    Processing block 7
    Processing block 2
    Processing block 4
    Processing block 5
    Processing block 6
    Processing block 9
    Processing block 10
    Processing block 8
    +++ Processed 10 blocks
    Processing block 12
    ...
    

    然而,这是混乱的混合。我做错了什么?感谢您的帮助。

    3 回复  |  直到 8 年前
        1
  •  2
  •   Faly    8 年前

    另一种解决方案是使用array reduce链接您的承诺:

    var groups = Array.from(new Array(10),(val,index) => 10*index);	// => [0, 10, 20, 30, 40, 50, 60, 70, 80, 90]
    groups.reduce((m, o) => {
        return m.then(() => {		
            var group = Array.from(new Array(10), (val, index) => o + index + 1);  // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [11, 12, 13, 14, 15, 16, 17, 18, 19, 20], ...
            var promises = group.map(i => this.web3.eth.getBlock(i).then(() => winston.info("Processing block " + i)) );
            return Promise.all(promises).then(() => winston.info("+++ Processed " + 10 + " blocks") );
        });
    }, Promise.resolve(true));   

    它只会给你预期的结果:

    enter image description here

        2
  •  1
  •   Nandu Kalidindi    8 年前

    因为你每次都要处理10个承诺,所以你可以 await 在每一批10人之后,还是会达不到目的?

    var promises = []; // You are mutating it so better not be a const
    var blockPromise = null;
    for (let i = 1; i <= 100; i ++) {
    
     blockPromise = this.web3.eth.getBlock(i).then((block: any) => {
          winston.info("Processing block " + i);
     }).catch((err: Error) => {
          winston.error(err);
     });
    
     promises.push(blockPromise);
    
     if (i % 10 === 0) {
         await Promise.all(promises);
         promises = [] // clear the processed promises as well
         winston.info("+++ Processed " + 10 + " blocks");
     }
    }
    
        3
  •  1
  •   Jonas Wilms    8 年前

    let promise = Promise.resolve(), promises = [];
    for( let i = 0; i <= 100; i++){
      promises.push(this.web3.eth.getBlock(i).then((block: any) => {
             winston.info("Processing block " + i);
         }).catch((err: Error) => {
             winston.error(err);
      }));
    
      if (i % 10 === 0){
       promise = Promise.all(promises.concat(promise))
          .then(_=>winston.info("+++ Processed " + 10 + " blocks");  
       promises = [];           
      }
    }