Serielle und parallele Operationen in JavaScript

Serielle und parallele Operationen in JavaScript

1. Einleitung

Dieser Artikel beschreibt die Lösungen für asynchrone Funktionen, serielle Ausführung und parallele Ausführung in es5 und es6 in js . Beispiele wurden in Kombination mit seriell und parallel verwendet.

2. es5-Methode

Bevor es6 herauskam, hatte die nodejs Community bereits eine promise -Lösung, um mit der Callback-Hölle umzugehen. Wenn mehrere asynchrone Funktionen vorhanden sind, wie sollte die Ausführungsreihenfolge angeordnet sein? Wie können alle asynchronen Funktionen schneller ausgeführt werden und dann mit dem nächsten Schritt fortgefahren werden? Hier tritt das Problem der seriellen und parallelen Ausführung von js auf.

3. Asynchrone Funktionsserienausführung

var Elemente = [ 1, 2, 3, 4, 5, 6 ];
var Ergebnisse = [];

Funktion async(Argument, Rückruf) {
  console.log('Parameter ist ' + arg +', gibt Ergebnis nach 1 Sekunde zurück');
  setTimeout(Funktion () { Rückruf(Argument * 2); }, 1000);
}

Funktion final(Wert) {
  console.log('Abgeschlossen: ', Wert);
}

Funktion Serie(Element) {
  wenn(Artikel) {
    async(Element, Funktion(Ergebnis) {
      Ergebnisse.push(Ergebnis);
      return series(items.shift()); // alle Daten rekursiv ausführen });
  } anders {
    return final(Ergebnisse[Ergebnisse.Länge - 1]);
  }
}

Serie (Elemente.Shift());

4. Parallele Ausführung asynchroner Funktionen

Die oben genannten Funktionen werden nacheinander ausgeführt, und die nächste wird ausgeführt, nachdem die vorherige abgeschlossen ist. Dies ähnelt async und await in es6 (nach es5 zusammenfassend als es6 bezeichnet). Gibt es so etwas wie promise.all , das alles parallel ausführen kann?

Wir können schreiben:

var Elemente = [ 1, 2, 3, 4, 5, 6 ];
var Ergebnisse = [];

Funktion async(Argument, Rückruf) {
  console.log('Parameter ist ' + arg +', gibt Ergebnis nach 1 Sekunde zurück');
  setTimeout(Funktion () { Rückruf(Argument * 2); }, 1000);
}

Funktion final(Wert) {
  console.log('Abgeschlossen: ', Wert);
}

items.forEach(Funktion(Element) {// Schleife abgeschlossen async(Element, Funktion(Ergebnis){
    Ergebnisse.push(Ergebnis);
    if(results.length === items.length) {// Bestimmen Sie, ob die Anzahl der abgeschlossenen Funktionen der Anzahl der auszuführenden Funktionen entspricht final(results[results.length - 1]);
    }
  })
});

5. Kombination der seriellen und parallelen Ausführung asynchroner Funktionen

Wenn viele asynchrone Daten (Hunderte davon) parallel ausgeführt werden und jede asynchrone Datei viele (https-)Anforderungsdaten enthält, führt dies zwangsläufig zu unzureichenden TCP-Verbindungen oder zur Ansammlung unzähliger Aufrufstapel, was zu einem Speicherüberlauf führt. Da es nicht einfach ist, zu viele Daten parallel auszuführen, entstand eine Kombination aus parallelen und seriellen Methoden.

Der Code kann wie folgt geschrieben werden:

var Elemente = [ 1, 2, 3, 4, 5, 6 ];
var Ergebnisse = [];
var läuft = 0;
Variablenlimit = 2;

Funktion async(Argument, Rückruf) {
  console.log('Parameter ist ' + arg +', gibt Ergebnis nach 1 Sekunde zurück');
  setTimeout(Funktion () { Rückruf(Argument * 2); }, 1000);
}

Funktion final(Wert) {
  console.log('Abgeschlossen: ', Wert);
}

Funktion Launcher() {
  während(läuft < Limit && Elemente.Länge > 0) {
    var item = items.shift();
    async(Element, Funktion(Ergebnis) {
      Ergebnisse.push(Ergebnis);
      läuft--;
      wenn (Elementlänge > 0) {
        Trägerrakete();
      } sonst wenn(läuft == 0) {
        endgültige(Ergebnisse);
      }
    });
    läuft++;
  }
}

Trägerrakete();

6. es6-Methode

es6 verfügt natürlich über serielle und parallele Ausführungsmethoden. Beispielsweise kann seriell async und await verwenden (im vorherigen Artikel erklärt), und parallel kann promise.all usw. verwenden. Um serielle und parallele Operationen zu kombinieren und die Anzahl gleichzeitiger promise all -Aufrufe zu begrenzen, hat die Community auch einige Lösungen parat, wie zum Beispiel

winziger asynchroner Pool, ES6-Promise-Pool, P-Limit


Einfache Kapselung einer Lösungsfunktion promise all gleichzeitigen Zahlenlimits

Funktion PromiseLimit(funcArray, limit = 5) { // 5 Daten gleichzeitig ausführen let i = 0;
  const Ergebnis = [];
  const wird ausgeführt = [];
  const Warteschlange = Funktion() {
    wenn (i === funcArray.length) return Promise.all(wird ausgeführt);
    const p = funcArray[i++]();
    Ergebnis.push(p);
    const e = p.then(() => ausführen.splice(ausführen.indexOf(e), 1));
    Ausführen von Push(e);
    wenn (Ausführungslänge >= Limit) {
      returniere Promise.race(Ausführen).dann(
        () => Warteschlange(),
        e => Versprechen.ablehnen(e)
      );
    }
    gibt Promise.resolve().then(() => queue()) zurück;
  };
  returniere queue().then(() => Promise.all(Ergebnis));
}

verwenden:

// Testcode const result = [];
für (let index = 0; index < 10; index++) {
  Ergebnis.push(Funktion() {
    returniere neues Promise((lösen, ablehnen) => {
      console.log("start" + index, neues Date().toLocaleString());
      setzeTimeout(() => {
        auflösen (Index);
        console.log("Ende" + index, neues Date().toLocaleString());
      }, parseInt(Math.random() * 10000));
    });
  });
}

PromiseLimit(Ergebnis).dann(Daten => {
  konsole.log(Daten);
});

Ändern Sie den Testcode und fügen Sie eine Zufallsfehlerlogik hinzu

// Ändern Sie den Testcode, sodass er nach dem Zufallsprinzip fehlschlägt oder erfolgreich ist const result = [];
für (let index = 0; index < 10; index++) {
  Ergebnis.push(Funktion() {
    returniere neues Promise((lösen, ablehnen) => {
      console.log("start" + index, neues Date().toLocaleString());
      setzeTimeout(() => {
        wenn (Math.random() > 0,5) {
          auflösen (Index);
        } anders {
          ablehnen(index);
        }
        console.log("Ende" + index, neues Date().toLocaleString());
      }, parseInt(Math.random() * 1000));
    });
  });
}
PromiseLimit(Ergebnis).dann(
  Daten => {
    console.log("Erfolg", Daten);
  },
  Daten => {
    console.log("fehlgeschlagen", Daten);
  }
);

7. async und await kombiniert mit promise all

asynchrone Funktion PromiseAll(promises,batchSize=10) {
 const Ergebnis = [];
 während(Versprechen.Länge > 0) {
   const data = warte auf Promise.all(promises.splice(0,batchSize));
   Ergebnis.push(...Daten);
 }
Ergebnis zurückgeben;
}

Es gibt zwei Probleme mit diesem Schreiben:

  • 1. promises werden vor dem Aufruf Promise.all erstellt, promise tatsächlich ausgeführt werden
  • 2. Ihre Implementierung muss warten, bis die vorherigen batchSize個promise resolve bevor die nächste batchSize ausgeführt wird. Das heißt, promise all müssen erfolgreich sein.

Die Verbesserungen sind wie folgt:

asynchrone Funktion asyncPool(Array,PoolLimit,IteratorFn) {
  Konstanten ret = [];
  const wird ausgeführt = [];
  für (const Element des Arrays) {
    const p = Promise.resolve().then(() => iteratorFn(item, array));
    ret.push(p);

    wenn (PoolLimit <= Array.Länge) {
      const e = p.then(() => ausführen.splice(ausführen.indexOf(e), 1));
      Ausführen von Push(e);
      wenn (Ausführungslänge >= PoolLimit) {
        warte auf Promise.race (Ausführung);
      }
    }
  }
  gibt Promise.all(ret) zurück;
}

verwenden:

const timeout = i => neues Versprechen(auflösen => setTimeout(() => auflösen(i), i));
return asyncPool( [1000, 5000, 3000, 2000], 2,timeout).dann(Ergebnisse => {
    ...
});

Dies ist das Ende dieses Artikels über serielle und parallele Operationen in asynchronen JavaScript-Operationen. Weitere relevante Inhalte zu seriellen und parallelen Operationen in asynchronen JavaScript-Operationen finden Sie in früheren Artikeln auf 123WORDPRESS.COM oder in den folgenden verwandten Artikeln. Ich hoffe, dass jeder 123WORDPRESS.COM in Zukunft unterstützen wird!

Das könnte Sie auch interessieren:
  • Zusammenfassung mehrerer gängiger Verarbeitungsmethoden für asynchrone JavaScript-Operationen
  • Lösen Sie das Problem der Verwendung von $q.all zum Sortieren der Reihenfolge der Hintergrundanforderungen für asynchrone Angularjs-Vorgänge
  • Detaillierte Erläuterung der asynchronen Operationsbeispiele von ES6-Javascript
  • async/await und promise (Problem mit asynchronem Betrieb in nodejs)
  • Synchroner und asynchroner Seitensprungvorgang bei Thinkjs
  • JavaScript - Lösen Sie den asynchronen Vorgang der Mongoose-Datenabfrage
  • Ein einfacher Node.js asynchroner Operationsmanager zum Teilen

<<:  HTML css js implementiert Tab-Seite Beispielcode

>>:  So ändern Sie die feste Positionierung untergeordneter Elemente durch CSS3-Transformation in eine absolute Positionierung

Artikel empfehlen

Tutorial zur Installation von VMWare15.5 unter Linux

Um VMWare unter Linux zu installieren, müssen Sie...

Data URI und MHTML Komplettlösung für alle Browser

Daten-URI Data URI ist ein durch RFC 2397 definie...

Ein Artikel, der Ihnen zeigt, wie Sie Vue-Komponenten erstellen und verwenden

Inhaltsverzeichnis 1. Was ist eine Komponente? 2....

So stellen Sie einen Redis 6.x-Cluster über Docker bereit

Systemumgebung: Redis-Version: 6.0.8 Docker-Versi...

Detaillierte Erklärung der Verwendung des Fuser-Befehls in Linux

beschreiben: fuser kann anzeigen, welches Program...

Zusammenfassung der Verwendung von JavaScript JSON.stringify()

Inhaltsverzeichnis 1. Nutzung 1. Grundlegende Ver...

Detaillierte Erklärung der React-Komponentenkommunikation

Inhaltsverzeichnis Einführung in die Komponentenk...

Ein Artikel zum Verständnis der Verwendung von Proxys in JavaScript

Inhaltsverzeichnis Was ist ein Agent Grundkenntni...

jQuery-Plugin zum Erzielen eines Code-Rain-Effekts

In diesem Artikel wird der spezifische Code des j...