In diesem Artikel werden hauptsächlich die Probleme und Lösungen beschrieben, die durch die im Nodejs-Entwicklungsprozess auftretenden Array-Eigenschaften verursacht werden, sowie die flexible Anwendung von Arrays. Die Testergebnisse dieses Artikels basieren auf Node v6.9.5 Arrays und WarteschlangenMit der Push/Shift-Methode des Array-Objekts kann beispielsweise die First-In-First-Out-Funktion der Warteschlange implementiert werden: >ein=[] [] >a.drücken(2.3.4) 3 >a.drücken(2) 3 >eine [2.3.4.2] >a.verschiebung() 2 >eine >[3.4.2] Arrays und forEachEs gibt zwei gängige Möglichkeiten, ein Array zu löschen: Löschen und die Verwendung der Splice-Methode. Der Unterschied zwischen ihnen muss deutlich gemacht werden.
Wenn Sie ein Element vollständig aus einem Array entfernen möchten, verwenden Sie splice: > a=[1,2,3] [ 1, 2, 3 ] > ein.spleißen(1,1) [ 2 ] > eine [ 1, 3 ] > a.Länge 2 > a.fürJeden(Funktion(Element, Index){Konsole.info("Index[", Index,"]:", Element)}); Index[ 0 ]: 1 index[ 1 ]: 3 undefiniert > Welchen Effekt hat also die Ausführung von forEach nach dem Löschen eines Elementobjekts mit delete? forEachs Verarbeitungsmechanismus für Arrays mit leeren ElementenDie Testergebnisse lauten wie folgt > a=[1,2,3] [ 1, 2, 3 ] > lösche a[1] WAHR > eine [ 1, , 3 ] > a.Länge 3 > a.fürJeden(Funktion(Element, Index){Konsole.info("Index[", Index,"]:", Element)}); Index[ 0 ]: 1 index[ 2 ]: 3 undefiniert Den Testergebnissen zufolge durchläuft forEach keine Elemente, deren Wert nicht definiert ist. In praktischen Anwendungen ist es eine große Herausforderung, festzustellen, ob forEach beendet ist. Um die asynchrone Funktionsanwendung von forEach zu lösen, können Sie dem Array einen Prototyp hinzufügen, um gültige Daten selbst zu verwalten und festzulegen. Die Wirkung ist wie folgt: > a=[1,2,3] [ 1, 2, 3 ] > a.gültigeNummer=3 3 > lösche a[2] WAHR > a.gültigeNummer=2 2 > eine [ 1, 2, , gültige Nummer: 2 ] > a.Länge 3 > a.gültige Nummer 2 > a.fürJeden(Funktion(Element, Index){Konsole.info("Index[", Index,"]:", Element)}); Index[ 0 ]: 1 index[ 1 ]: 2 undefiniert > Ergänzung: Node.js-Array forEach verarbeitet Kontextanweisungen synchron Ich bin an die Denkweise der C-Sprache gewöhnt und als ich zum ersten Mal mit Node.js in Berührung kam, bereitete mir die asynchrone Verarbeitung Kopfschmerzen. Beim Schreiben von Code kann es vorkommen, dass Sie die Elemente eines Arrays in einer Schleife verarbeiten und dann nach Abschluss der gesamten Verarbeitung eine letzte Operation ausführen müssen. Aufgrund der asynchronen Natur von JS wird diese letzte Anweisung jedoch zuerst ausgeführt. Nehmen Sie sich also etwas Zeit, um forEach zu studieren. Reden ist billig. Zeigen Sie mir den Code. forEach-VerwendungforEach wird zum Durchlaufen der Array-Struktur verwendet. Ich habe jemanden sagen hören, dass forEach auf der untersten Ebene mithilfe von for implementiert wird. Ich habe es nicht eingehend untersucht, aber zumindest scheint der Effekt derselbe zu sein. Die drei Parameter der Rückruffunktion von forEach sind: Wert, Sequenznummer und ursprüngliches Array. Die Sequenznummer beginnt bei 0. (() => { sei arr = [2, 3, 1]; arr.forEach(Funktion (Wert, Index, Array) { konsole.log(Wert); konsole.log(index); Konsole.log(Array); konsole.log('-----'); }); })(); Ausgabe 2 0 [ 2, 3, 1 ] ----- 3 1 [ 2, 3, 1 ] ----- 1 2 [ 2, 3, 1 ] ----- Aus den Ergebnissen ist ersichtlich, dass die mehreren Schleifen von forEach synchronisiert sind, das heißt, sie werden nacheinander ausgeführt. Wenn ich aber daran denke, dass es sich um JS handelt, erscheint mir eine Synchronisierung unmöglich. . Sie können es überprüfen. forEach verarbeitet asynchron mehrere SchleifenDieses Mal wird eine Timer-Aufgabe zu forEach hinzugefügt und jeder Schleifenvorgang wird um die mit dem Wert verbundene Zeit verzögert, um einen zeitaufwändigeren Vorgang zu simulieren. (() => { sei arr = [2, 3, 1]; arr.forEach(Funktion (Wert, Index, Array) { setzeTimeout(Funktion () { konsole.log(Wert); }, Wert*100); }); })(); Ausgabe 1 2 3 Aus den Ergebnissen können wir ersehen, dass die Aufgabe mit der kürzesten Zeit zuerst abgeschlossen wird und die Aufgaben jeder Schleife nicht in der Reihenfolge der Schleife ausgeführt werden, d. h. mehrere Schleifen werden asynchron verarbeitet. forEach-Kontext wird ebenfalls asynchron ausgeführtZurück zum eingangs erwähnten Problem: Unabhängig davon, ob die mehreren Schleifen nacheinander ausgeführt werden, muss ich nach Abschluss aller Aufgaben in forEach ein Datenelement ausführen, um mich darüber zu benachrichtigen, dass alle Aufgaben abgeschlossen sind. (() => { sei arr = [2, 3, 1]; arr.forEach(Funktion (Wert, Index, Array) { setzeTimeout(Funktion () { konsole.log(Wert); }, Wert*100); }); console.log('Die ganze Arbeit ist erledigt'); })(); Ausgabe Die ganze Arbeit ist erledigt 1 2 3 Den Ergebnissen zufolge sind auch die Kontextanweisungen nicht synchronisiert. Die Aufgabe in der forEach-Schleife wird nicht abgeschlossen, bevor die Meldung angezeigt wird, dass alle Aufgaben abgeschlossen sind, was offensichtlich nicht den Erwartungen entspricht. Ich habe viele Blogs zu diesem Problem gelesen, konnte aber keine passende Lösung finden. Schließlich konnte ich diese Funktion nur mit Promise.all implementieren. Promise.all implementiert die synchrone Verarbeitung von forEach-KontextanweisungenÄndern Sie den obigen Code in die Promise.all-Struktur. Am Ende jeder Schleife wird resolve() aufgerufen. Wir wissen, dass die then-Funktion von Promise.all nur ausgelöst wird, wenn alle Promises ausgeführt wurden, was unseren Anforderungen zu entsprechen scheint. (() => { sei arr = [2, 3, 1]; sei proArr = []; arr.forEach(Funktion (Wert, Index) { proArr[index] = neues Promise(Funktion (auflösen) { setzeTimeout(Funktion () { konsole.log(Wert); lösen(); }, Wert*100); }); }); Versprechen.alles(proArr).then(()=>{ console.log('Die ganze Arbeit ist erledigt'); }) })(); Ausgabe 1 2 3 Die ganze Arbeit ist erledigt Den Ergebnissen zufolge wurden unsere Anforderungen erfüllt. Mögliche ProblemeAls ich über die asynchronen Eigenschaften von JS nachdachte, wurde mir plötzlich klar, dass bei dieser Methode möglicherweise ein Problem vorliegt. Hier wird bei jedem Aufruf von forEach das Promise-Array zugewiesen. Dieser Vorgang sollte sehr kurz sein. Die letzte Promise.all-Anweisung wird erst aufgerufen, nachdem die Zuweisung in den drei Schleifen abgeschlossen ist. Wenn das Array jedoch sehr groß ist und die Zuweisungsoperation in der Schleife sehr zeitaufwändig ist und nur die Hälfte der Zuweisungsoperation abgeschlossen ist, ist das bei der Ausführung des letzten Promise.all übergebene Promise-Array möglicherweise nicht das Array, das alle Promises enthält. In diesem Fall wartet Promise.all nur auf die Hälfte der Vorgänge. Wenn Promise.all wartet, ist nicht bekannt, ob auf das am Ende des Arrays zugewiesene Promise gewartet wird. Ich habe gerade erst mit der Verwendung von JS begonnen und verstehe den Implementierungsmechanismus nicht. Daher kann ich nur experimentieren, um zu überprüfen, ob dieses Problem besteht. Als nächstes vergrößern wir dieses Array. Bitte verzeihen Sie mir, dass ich den sichersten Weg gewählt habe, um es zu vergrößern. (() => { sei arr = [2, 3, 1, 2, 3, 1, 2, 3, 1, 2]; // 10 arr = arr.concat(arr); // 2^1 * 10 arr = arr.concat(arr); // 2^2 * 10 arr = arr.concat(arr); // 2^3 arr = arr.concat(arr); // 2^4 arr = arr.concat(arr); // 2^5 arr = arr.concat(arr); arr = arr.concat(arr); arr = arr.concat(arr); arr = arr.concat(arr); arr = arr.concat(arr); // 2^10 arr = arr.concat(arr); arr = arr.concat(arr); arr = arr.concat(arr); arr = arr.concat(arr); arr = arr.concat(arr); // 2^15 arr = arr.concat(arr); arr = arr.concat(arr); // 2^17 * 10 // arr = arr.concat(arr); // 2^18 * 10 Konsole.log(arr.Länge); sei proArr = []; arr.forEach(Funktion (Wert, Index) { proArr[index] = neues Promise(Funktion (auflösen) { setzeTimeout(Funktion () { konsole.log(Wert); lösen(); }, Wert*100); }); }); Versprechen.alles(proArr).then(()=>{ console.log('Die ganze Arbeit ist erledigt'); Konsole.log(arr.Länge); }).catch(Funktion (Fehler) { console.log(fehler); }) })(); Nach dem Testen auf meinem Computer meldet Promise bei einer Array-Länge von 2^18 * 10 einen RangeError-Fehler: Zu viele Elemente an Promise.all übergeben. Wenn die Array-Länge 2^17 * 10 oder 2621440 beträgt, wird es normal ausgeführt. Nach mehrmaligem Testen wird die Ausgabe des zuletzt ausgeführten Befehls „Die gesamte Arbeit ist erledigt“ immer am Ende ausgegeben (da der Terminalpuffer zu klein ist, wird das Ausgabeergebnis mithilfe der Umleitung node xx.js > log.txt in eine Datei zur Anzeige umgeleitet). Natürlich wird es in der Anwendung kein so großes Array geben. Den Ergebnissen nach zu urteilen, treten die oben genannten Probleme in tatsächlichen Anwendungen nicht auf. Das heißt, Promise.all kann verwendet werden, um die synchrone Verarbeitung von forEach-Kontextanweisungen zu implementieren. Das Obige ist meine persönliche Erfahrung. Ich hoffe, es kann Ihnen als Referenz dienen. Ich hoffe auch, dass Sie 123WORDPRESS.COM unterstützen werden. Sollten dennoch Fehler oder unvollständige Überlegungen vorliegen, freue ich mich über eine Korrektur. Das könnte Sie auch interessieren:
|
<<: MySQL-Trigger: ausführliche Erklärung und einfaches Beispiel
>>: Beispielcode für die Batchbereitstellung von Nginx mit Ansible
In diesem Artikel wird der spezifische Code von j...
Inhaltsverzeichnis Komponentendesign Definieren d...
Was ist die Nginx-Zugriffsbeschränkungskonfigurat...
Link zum Download der ZIP-Datei auf der offiziell...
In diesem Artikelbeispiel wird der spezifische Ja...
Zusätzliche Erklärung, Fremdschlüssel: Verwenden ...
Konfigurieren Sie ein Implementierungsbeispiel fü...
Warum hat CSS einen Kaskadierungsmechanismus? Da ...
Inhaltsverzeichnis 1. filter() 2. fürJedes() 3. e...
①. So verwenden Sie den Alias-Eintrag (CNAME): Be...
1. Was ist die HTML-Auszeichnungssprache? HTML is...
<br />Ich habe festgestellt, dass viele Leut...
Informationen zum Miniprogramm-Datencache Datenca...
In diesem Artikelbeispiel wird der spezifische Co...
1. Z-Index ist in IE6 ungültig. In CSS wird die E...