1. Einführung in die ParallelitätskontrolleAngenommen, es stehen 6 ausstehende Aufgaben zur Ausführung an und wir möchten die Anzahl der Aufgaben begrenzen, die gleichzeitig ausgeführt werden können, d. h., es können höchstens 2 Aufgaben gleichzeitig ausgeführt werden. Wenn eine beliebige Aufgabe in der Liste der ausgeführten Aufgaben abgeschlossen ist, ruft das Programm automatisch eine neue zu erledigende Aufgabe aus der Liste der zu erledigenden Aufgaben ab und fügt die Aufgabe der Liste der ausgeführten Aufgaben hinzu. Damit jeder den obigen Vorgang intuitiver verstehen kann, hat Bruder Abao speziell die folgenden 3 Bilder gezeichnet: 1.1 Phase 11.2 Phase 21.3 Phase 3Okay, nachdem ich die Parallelitätssteuerung vorgestellt habe, werde ich die Async-Pool-Bibliothek auf Github verwenden, um die spezifische Implementierung der asynchronen Task-Parallelitätssteuerung vorzustellen. https://github.com/rxaviers/async-pool Führen Sie mehrere Promise-Returning- und asynchrone Funktionen mit begrenzter Parallelität unter Verwendung von nativem ES6/ES7 aus. 2. Implementierung der ParallelitätskontrolleDie async-pool-Bibliothek bietet zwei verschiedene Implementierungsversionen: ES7 und ES6. Bevor wir die spezifische Implementierung analysieren, schauen wir uns an, wie sie verwendet wird. 2.1 Verwendung von asyncPoolconst timeout = i => neues Versprechen(auflösen => setTimeout(() => auflösen(i), i)); warte auf asyncPool(2, [1000, 5000, 3000, 2000], Timeout); Im obigen Code verwenden wir die von der Async-Pool-Bibliothek bereitgestellte Funktion AsyncPool, um die gleichzeitige Steuerung asynchroner Aufgaben zu implementieren. Die Signatur der Funktion asyncPool lautet wie folgt: Funktion asyncPool(PoolLimit, Array, IteratorFn){ ... } Diese Funktion erhält 3 Parameter:
Für das obige Beispiel sieht der entsprechende Ausführungsprozess nach Verwendung der Funktion asyncPool wie folgt aus: const timeout = i => neues Versprechen(auflösen => setTimeout(() => auflösen(i), i)); warte auf asyncPool(2, [1000, 5000, 3000, 2000], Timeout); //Iterator aufrufen (i = 1000) //Iterator aufrufen (i = 5000) // Pool-Limit von 2 erreicht, warten Sie, bis der Schnellere fertig ist … // 1000 Abschlüsse //Iterator aufrufen (i = 3000) // Pool-Limit von 2 erreicht, warten Sie, bis der Schnellere fertig ist … // 3000 Abschlüsse //Iterator aufrufen (i = 2000) // Iteration ist abgeschlossen. Warten Sie, bis die laufenden Iterationen abgeschlossen sind … // 5000 Abschlüsse // 2000 Zielankünfte // Wird aufgelöst, Ergebnisse werden in der angegebenen Array-Reihenfolge `[1000, 5000, 3000, 2000]` übergeben. Durch Beachten der obigen Kommentare können wir den Kontrollfluss innerhalb der Funktion asyncPool grob verstehen. Als nächstes analysieren wir die ES7-Implementierung der asyncPool-Funktion. 2.2 asyncPool ES7-Implementierungasynchrone Funktion asyncPool(PoolLimit, Array, IteratorFn) { const ret = []; // Alle asynchronen Aufgaben speichern const executing = []; // Die asynchronen Aufgaben speichern, die ausgeführt werden für (const item of array) { // Rufen Sie die Funktion iteratorFn auf, um eine asynchrone Aufgabe zu erstellen. const p = Promise.resolve().then(() => iteratorFn(item, array)); ret.push(p); // Neue asynchrone Aufgaben speichern // Wenn der PoolLimit-Wert kleiner oder gleich der Gesamtzahl der Aufgaben ist, führe eine Parallelitätskontrolle durch, wenn (PoolLimit <= Array.Länge) { // Wenn die Aufgabe abgeschlossen ist, entfernen Sie die abgeschlossene Aufgabe aus dem Array der ausgeführten Aufgaben const e = p.then(() => executing.splice(executing.indexOf(e), 1)); executing.push(e); // Speichere die ausgeführte asynchrone Aufgabe, wenn (executing.length >= poolLimit) { warte auf Promise.race(executing); // Warte, bis die schnellere Aufgabe abgeschlossen ist } } } gibt Promise.all(ret) zurück; } Im obigen Code werden die Funktionen Promise.all und Promise.race vollständig genutzt und mit der in ES7 bereitgestellten asynchronen Wartefunktion kombiniert, um schließlich die Parallelitätssteuerungsfunktion zu realisieren. Mit der Anweisung „await Promise.race(executing);“ warten wir, bis die schnelleren Aufgaben in der Liste der ausgeführten Aufgaben abgeschlossen sind, bevor wir mit der nächsten Schleife fortfahren. Die Implementierung von asyncPool ES7 ist relativ einfach. Als Nächstes sehen wir uns an, wie man die gleiche Funktionalität erreicht, ohne die Funktion „async await“ zu verwenden. 2.3 asyncPool ES6-ImplementierungFunktion asyncPool(PoolLimit, Array, IteratorFn) { sei i = 0; const ret = []; // Alle asynchronen Aufgaben speichern const executing = []; // In Ausführung befindliche asynchrone Aufgaben speichern const enqueue = function () { wenn (i === Array.Länge) { gibt Promise.resolve() zurück; } const item = array[i++]; // Neues Task-Element abrufen const p = Promise.resolve().then(() => iteratorFn(item, array)); ret.push(p); lass r = Promise.resolve(); // Wenn der PoolLimit-Wert kleiner oder gleich der Gesamtzahl der Aufgaben ist, führen Sie eine Parallelitätskontrolle durch, wenn (PoolLimit <= Array.Länge) { // Wenn die Aufgabe abgeschlossen ist, entfernen Sie die abgeschlossene Aufgabe aus dem Array der ausgeführten Aufgaben const e = p.then(() => executing.splice(executing.indexOf(e), 1)); Ausführen von Push(e); wenn (Ausführungslänge >= PoolLimit) { r = Promise.race(wird ausgeführt); } } // Nachdem die schnelleren Aufgaben in der ausgeführten Aufgabenliste abgeschlossen sind, werden neue Aufgaben aus dem Array abgerufen array return r.then(() => enqueue()); }; : return enqueue().then(() => Promise.all(ret)); } In der ES6-Implementierung wird die Kernsteuerungslogik durch die interne Enqueue-Funktion implementiert. Wenn das von Promise.race(executing) zurückgegebene Promise-Objekt abgeschlossen ist, wird die Enqueue-Funktion aufgerufen, um die neue zu erledigende Aufgabe aus dem Array abzurufen. 3. Bruder Abao hat etwas zu sagenIn den ES7- und ES6-Implementierungen der asyncPool-Bibliothek haben wir die Funktionen Promise.all und Promise.race verwendet. Darunter ist das handschriftliche Verfassen von „Promise.all“ eine häufige Frage im Vorstellungsgespräch. Bruder Abao nutzt einfach diese Gelegenheit und wird mit allen eine einfache Version der Funktionen Promise.all und Promise.race schreiben. 3.1 Handschriftliches Versprechen.alleDie Methode Promise.all(iterable) gibt ein Promise-Objekt zurück. Wenn der Status aller eingegebenen Promise-Objekte aufgelöst wird, gibt das zurückgegebene Promise-Objekt die Ergebnisse jedes Promise-Objekts nach der Auflösung in Form eines Arrays zurück. Wenn der Status eines beliebigen eingegebenen Promise-Objekts auf „Abgelehnt“ gesetzt wird, wird das zurückgegebene Promise-Objekt mit der entsprechenden Fehlermeldung abgelehnt. Promise.all = Funktion (Iteratoren) { returniere neues Promise((lösen, ablehnen) => { if (!Iteratoren || Iteratoren.Länge === 0) { lösen([]); } anders { let count = 0; // Zähler, der bestimmt, ob alle Aufgaben abgeschlossen wurden let result = []; // Ergebnis-Array for (let i = 0; i < iterators.length; i++) { // Da es sich bei iterators[i] um ein normales Objekt handeln kann, wird es als Promise-Objekt verpackt Promise.resolve(iterators[i]).then( (Daten) => { result[i] = data; // Speichere die entsprechenden Ergebnisse der Reihe nach // Wenn alle Aufgaben erledigt sind, gib die Ergebnisse einheitlich zurück if (++count === iterators.length) { Lösung (Ergebnis); } }, (fehler) => { reject(err); // Wenn die Ausführung eines Promise-Objekts fehlschlägt, wird die Methode reject() aufgerufen. return; } ); } } }); }; Es ist zu beachten, dass bei der Standardimplementierung von Promise.all der Parameter ein iterierbares Objekt wie Array, String oder Set ist. 3.2 Handschriftliches Promise.raceDie Methode Promise.race(iterable) gibt ein Promise-Objekt zurück. Sobald ein Promise-Objekt im Iterator aufgelöst oder abgelehnt wird, löst das zurückgegebene Promise-Objekt den entsprechenden Wert auf oder lehnt ihn ab. Promise.race = Funktion (Iteratoren) { returniere neues Promise((lösen, ablehnen) => { für (const iter von Iteratoren) { Versprechen.lösen(iter) .then((res) => { Entschlossenheit (res); }) .catch((e) => { ablehnen(e); }); } }); }; In diesem Artikel analysiert Abao Ge detailliert die spezifische Implementierung der asynchronen Task-Parallelitätssteuerung von Async-Pool und ermöglicht gleichzeitig jedem ein besseres Verständnis des Kerncodes von Async-Pool. Schließlich leitete Bruder Abao alle an, eine einfache Version der Funktionen Promise.all und Promise.race zu schreiben. Tatsächlich gibt es neben der Funktion Promise.all noch eine weitere Funktion - Promise.allSettled, die zur Lösung der Probleme von Promise.all verwendet wird. Interessierte Freunde können sie selbst studieren. IV. Referenzressourcen Github - asynchroner Pool Oben finden Sie Einzelheiten zur Implementierung der Parallelitätssteuerung in JavaScript. Weitere Informationen zur JavaScript-Parallelitätssteuerung finden Sie in den anderen verwandten Artikeln auf 123WORDPRESS.COM! Das könnte Sie auch interessieren:
|
<<: MySQL-FAQ-Serie: So vermeiden Sie eine plötzliche Vergrößerung der ibdata1-Datei
>>: So verwenden Sie limit_req_zone in Nginx, um den Zugriff auf dieselbe IP zu beschränken
Inhaltsverzeichnis 1. Ergebnisse erzielen 2. Back...
Inhaltsverzeichnis 1. Übersicht 1. Grundsatz 2. U...
CSS-Medienabfragen haben ein sehr praktisches Sei...
Inhaltsverzeichnis Standards für flüssige Animati...
Inhaltsverzeichnis Tabelle/index.js Tabelle/Model...
Installieren Sie FFmpeg flac eric@ray:~$ sudo apt...
Inhaltsverzeichnis 1. Warum ist JavaScript Single...
1. Prozentuale Basis für Elementbreite/-höhe/-pol...
Eingabe-Subsystem-Framework Das Linux-Eingabesubs...
Heute habe ich mir einige Dinge im Zusammenhang m...
Object.defineProperty verstehen Grammatik: Object...
Vorwort Hallo zusammen, hier ist der CSS-Assisten...
Nachdem Sie Docker auf dem Linux-Server installie...
Einführung Ich habe schon einmal ein Problem fest...
Verzögertes Laden (Lazy Loading) und Vorladen sin...