2017-10-30 2 views
3

Ich habe eine Schleife von 100 Versprechen. Ich möchte 10 davon gleichzeitig verarbeiten, dann eine Aussage drucken und mit den nächsten 10 parallel fortfahren. Es wartet jedoch nicht auf alle 10 Versprechen, ihre Ausführung zu beenden.JavaScript/TypeScript - Schleife der Versprechen wartet nicht

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); 
     }); 
    } 

Meine Erwartung ist, so etwas wie:

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 
... 

Jedoch wird es chaotisch durcheinander. Was mache ich falsch? Jede Hilfe wird geschätzt.

+0

Sie müssen die 'Promise.all' aus Ihrer Schleife verschieben, da Ihre Versprechen mehrere Male aufgerufen werden, wenn Sie das Array der Versprechen füllen. – 3Dos

+0

Wenn ich 'Promise.all' außerhalb der Schleife anrufe, verarbeitet es alle 100 von ihnen parallel, oder? Was ich will, ist nur 10 parallel zu bearbeiten, dann eine andere Aktion, dann wieder 10 parallel, und so weiter – phoebus

+1

Sie können 'Promise.all' nicht mit einer Callback-Methode innerhalb einer' for-Schleife' verwenden und erwarten '' -loop warten Sie könnten 'async/await' verwenden, um das zu tun. – Danmoreng

Antwort

1

Da Sie versuchen, 10 Versprechen jedes Mal zu verarbeiten, könnten Sie await nach jeder Charge von 10 oder würde das den Zweck besiegen?

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"); 
} 
} 
+0

Es ist nicht notwendig BlockPromise zu erwarten. Bitte versuchen Sie dieses Snippet in Ihrer Konsole 'k = neue Versprechen ((auflösen, ablehnen) => auflösen (" HALLO "))' 'q = neue Versprechen ((auflösen, ablehnen) => auflösen (" Q Hallo ")) ' ' arr = [k, q] ' ' erwarten Promise.all (arr) ' –

+0

' async/erwarten 'tat den Trick - danke. @ Jonasw warum sollte blockPromise ein warten? – phoebus

+0

Wenn 'blockPromise' erwartet wird, wird Ihre Ausführung sequentiell, genau wie eine einfache Schleife. –

1

Versprechungen innen für Schleifen versauen alles. Entweder Sie verwenden async und warten, oder Sie brauchen, um das Ganze zu einem Versprechen Kette zu reduzieren:

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 = [];   
    } 
} 
2

Eine andere Lösung ist Array zu verwenden reduzieren Kette Ihr Versprechen:

var groups = Array.from(new Array(10),(val,index) => 10*index); \t // => [0, 10, 20, 30, 40, 50, 60, 70, 80, 90] 
 
groups.reduce((m, o) => { 
 
    return m.then(() => { \t \t 
 
     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));

Es gibt nur das erwartete Ergebnis:

enter image description here

Verwandte Themen