JavaScript, Node.js: ist Array.forEach asynchron?

Lesezeit: 7 Minuten

JavaScript Nodejs ist ArrayforEach asynchron
R. Gr.

Ich habe eine Frage zu den Eingeborenen Array.forEach Implementierung von JavaScript: Verhält es sich asynchron? Wenn ich zum Beispiel anrufe:

[many many elements].forEach(function () {lots of work to do})

Wird dies nicht blockierend sein?

  • siehe auch Sind alle Callback-Funktionen von Node.js asynchron?

    – Bergi

    21. April 2016 um 0:50 Uhr

JavaScript Nodejs ist ArrayforEach asynchron
Felix Klinge

Nein, es blockiert. Schauen Sie sich die an Spezifikation des Algorithmus.

Es wird jedoch eine vielleicht einfacher verständliche Implementierung angegeben MDN:

if (!Array.prototype.forEach)
{
  Array.prototype.forEach = function(fun /*, thisp */)
  {
    "use strict";

    if (this === void 0 || this === null)
      throw new TypeError();

    var t = Object(this);
    var len = t.length >>> 0;
    if (typeof fun !== "function")
      throw new TypeError();

    var thisp = arguments[1];
    for (var i = 0; i < len; i++)
    {
      if (i in t)
        fun.call(thisp, t[i], i, t);
    }
  };
}

Wenn Sie für jedes Element viel Code ausführen müssen, sollten Sie einen anderen Ansatz in Betracht ziehen:

function processArray(items, process) {
    var todo = items.concat();

    setTimeout(function() {
        process(todo.shift());
        if(todo.length > 0) {
            setTimeout(arguments.callee, 25);
        }
    }, 25);
}

und rufe es dann auf mit:

processArray([many many elements], function () {lots of work to do});

Dies wäre dann nicht blockierend. Das Beispiel ist entnommen Hochleistungs-JavaScript.

Eine andere Möglichkeit wäre evtl Webarbeiter.

  • Wenn Sie Node.js verwenden, ziehen Sie auch die Verwendung von in Betracht process.nextTick statt setTimeout

    – Marcello Bastea-Forte

    19. Februar 2011 um 15:40 Uhr

  • Technisch gesehen “blockiert” forEach nicht, da die CPU niemals in den Ruhezustand geht. Es ist synchron und CPU-gebunden, was sich wie „Blockieren“ anfühlen kann, wenn Sie erwarten, dass die Node-App auf Ereignisse reagiert.

    – David Dopson

    2. August 2011 um 17:58 Uhr

  • asynchron wäre hier wahrscheinlich eine geeignetere Lösung (tatsächlich habe ich gerade gesehen, dass jemand das als Antwort gepostet hat!).

    – James

    4. Juli 2014 um 13:27 Uhr


  • Ich habe dieser Antwort vertraut, aber sie scheint in einigen Fällen falsch zu sein. forEach tut nicht Block an await Anweisungen zum Beispiel und Sie sollten lieber a verwenden for Schleife: stackoverflow.com/questions/37962880/…

    – Richard

    22. Juni 2016 um 9:27 Uhr


  • @Richard: natürlich. Sie können nur verwenden await Innerhalb async Funktionen. Aber forEach weiß nicht, was asynchrone Funktionen sind. Denken Sie daran, dass asynchrone Funktionen nur Funktionen sind, die ein Versprechen zurückgeben. Würdest du erwarten forEach ein vom Rückruf zurückgegebenes Versprechen verarbeiten? forEach ignoriert den Rückgabewert des Callbacks vollständig. Es wäre nur in der Lage, einen asynchronen Rückruf zu verarbeiten, wenn es selbst asynchron wäre.

    – Felix Klinge

    22. Juni 2016 um 14:27 Uhr


1646171121 632 JavaScript Nodejs ist ArrayforEach asynchron
Caolan

Wenn Sie eine asynchronfreundliche Version von Array.forEach und ähnlich sind sie im Node.js-Modul „async“ verfügbar: http://github.com/caolan/async …als Bonus funktioniert dieses Modul auch im Browser.

async.each(openFiles, saveFile, function(err){
    // if any of the saves produced an error, err would equal that error
});

  • Wenn Sie sicherstellen müssen, dass der asynchrone Vorgang ausgeführt wird jeweils nur ein Exemplar (in der Reihenfolge der Abholung)Sie müssen verwenden eachSeries stattdessen.

    – Matpop

    9. Mai 2018 um 9:25 Uhr

  • @JohnKennedy Ich habe dich schon mal gesehen!

    – Xsmael

    3. Oktober 2019 um 10:16 Uhr

JavaScript Nodejs ist ArrayforEach asynchron
David Dopson

Es gibt ein allgemeines Muster für eine wirklich umfangreiche Berechnung in Node, das möglicherweise auf Sie zutrifft …

Node ist Single-Threaded (als bewusste Designentscheidung siehe Was ist Node.js?); Dies bedeutet, dass nur ein einzelner Kern verwendet werden kann. Moderne Boxen haben 8, 16 oder sogar mehr Kerne, sodass mehr als 90 % der Maschine im Leerlauf bleiben könnten. Das übliche Muster für einen REST-Dienst besteht darin, einen Knotenprozess pro Kern zu starten und diesen hinter einem lokalen Load Balancer wie z http://nginx.org/.

Ein Kind gabeln – Für das, was Sie zu tun versuchen, gibt es ein weiteres gängiges Muster, nämlich das Abzweigen eines untergeordneten Prozesses, um die schwere Arbeit zu erledigen. Der Vorteil ist, dass der untergeordnete Prozess im Hintergrund umfangreiche Berechnungen durchführen kann, während Ihr übergeordneter Prozess auf andere Ereignisse reagiert. Der Haken ist, dass Sie den Speicher nicht mit diesem untergeordneten Prozess teilen können / sollten (nicht ohne VIELE Verzerrungen und etwas nativen Code); Sie müssen Nachrichten weitergeben. Dies funktioniert wunderbar, wenn die Größe Ihrer Eingabe- und Ausgabedaten im Vergleich zu der durchzuführenden Berechnung klein ist. Sie können sogar einen untergeordneten node.js-Prozess starten und denselben Code verwenden, den Sie zuvor verwendet haben.

Zum Beispiel:

var child_process = require('child_process');
function run_in_child(array, cb) {
    var process = child_process.exec('node libfn.js', function(err, stdout, stderr) {
        var output = JSON.parse(stdout);
        cb(err, output);
    });
    process.stdin.write(JSON.stringify(array), 'utf8');
    process.stdin.end();
}

  • Nur um es klar zu sagen … Node ist kein Single-Thread, aber die Ausführung Ihres JavaScripts ist es. IO und was nicht läuft auf separaten Threads.

    – Brad

    11. Januar 2013 um 18:45 Uhr

  • @Brad – vielleicht. das ist implementierungsabhängig. Bei entsprechender Kernel-Unterstützung kann die Schnittstelle zwischen Node und dem Kernel ereignisbasiert sein – kqueue (Mac), epoll (Linux), IO-Completion-Ports (Windows). Als Fallback funktioniert auch ein Pool von Threads. Ihr grundlegender Punkt ist jedoch richtig. Die Low-Level-Node-Implementierung kann mehrere Threads haben. Aber sie werden sie NIEMALS direkt dem JS-Benutzerland aussetzen, da dies das gesamte Sprachmodell zerstören würde.

    – David Dopson

    11. Januar 2013 um 20:51 Uhr

  • Richtig, ich stelle das nur klar, weil das Konzept viele verwirrt hat.

    – Brad

    12. Januar 2013 um 6:40 Uhr

Array.forEach ist für die Berechnung von Dingen gedacht, die nicht warten, und es ist nichts zu gewinnen, wenn Berechnungen in einer Ereignisschleife asynchron durchgeführt werden (Webworker fügen Multiprocessing hinzu, wenn Sie Multicore-Berechnungen benötigen). Wenn Sie auf das Ende mehrerer Aufgaben warten möchten, verwenden Sie einen Zähler, den Sie in eine Semaphor-Klasse einschließen können.

1646171122 448 JavaScript Nodejs ist ArrayforEach asynchron
Josh Mc

Bearbeiten 11.10.2018: Es sieht so aus, als ob der unten beschriebene Standard möglicherweise nicht durchkommt, bedenken Sie Rohrleitungen als Alternative (verhält sich nicht genau gleich, aber Methoden könnten auf ähnliche Weise implementiert werden).

Genau aus diesem Grund freue ich mich über es7, in Zukunft werden Sie in der Lage sein, so etwas wie den folgenden Code zu tun (einige der Spezifikationen sind nicht vollständig, also mit Vorsicht verwenden, ich werde versuchen, dies auf dem neuesten Stand zu halten). Aber im Grunde können Sie mit dem neuen :: bind-Operator eine Methode auf einem Objekt ausführen, als ob der Prototyp des Objekts die Methode enthält. z.B [Object]::[Method] wo Sie normalerweise anrufen würden [Object].[ObjectsMethod]

Um dies heute (24. Juli 16) zu tun und in allen Browsern zu funktionieren, müssen Sie Ihren Code für die folgende Funktionalität transpilieren:Import Export, Pfeilfunktionen, Versprechen, Asynchron / Warten und am wichtigsten Funktion binden. Der folgende Code könnte geändert werden, um nur die Funktion bind zu verwenden, falls erforderlich, all diese Funktionalität ist heute ordentlich verfügbar, indem verwendet wird babel.

YourCode.js (wobei ‘viel zu tun‘ muss einfach ein Promise zurückgeben und es auflösen, wenn die asynchrone Arbeit erledigt ist.)

import { asyncForEach } from './ArrayExtensions.js';

await [many many elements]::asyncForEach(() => lots of work to do);

ArrayExtensions.js

export function asyncForEach(callback)
{
    return Promise.resolve(this).then(async (ar) =>
    {
        for(let i=0;i<ar.length;i++)
        {
            await callback.call(ar, ar[i], i, ar);
        }
    });
};

export function asyncMap(callback)
{
    return Promise.resolve(this).then(async (ar) =>
    {
        const out = [];
        for(let i=0;i<ar.length;i++)
        {
            out[i] = await callback.call(ar, ar[i], i, ar);
        }
        return out;
    });
};

1646171123 949 JavaScript Nodejs ist ArrayforEach asynchron
Rax Wunter

Dies ist eine kurze asynchrone Funktion, die verwendet werden kann, ohne dass Bibliotheken von Drittanbietern erforderlich sind

Array.prototype.each = function (iterator, callback) {
    var iterate = function () {
            pointer++;
            if (pointer >= this.length) {
                callback();
                return;
            }
            iterator.call(iterator, this[pointer], iterate, pointer);
    }.bind(this),
        pointer = -1;
    iterate(this);
};

1646171124 64 JavaScript Nodejs ist ArrayforEach asynchron
Philipp Kirkbride

Es gibt ein Paket auf npm für easy asynchron für jede Schleife.

var forEachAsync = require('futures').forEachAsync;

// waits for one request to finish before beginning the next 
forEachAsync(['dogs', 'cats', 'octocats'], function (next, element, index, array) {
  getPics(element, next);
  // then after all of the elements have been handled 
  // the final callback fires to let you know it's all done 
  }).then(function () {
    console.log('All requests have finished');
});

Auch eine andere Variante fürAllAsync

905180cookie-checkJavaScript, Node.js: ist Array.forEach asynchron?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy