JustMe28: Frage zu fetch und Übergabe von Array, Aufruf aus anderer .js

Hallo Gemeinde,

Frage ist vllt. etwas komplex, versuche mal so klar wie möglich zu beschreiben:

Folgendes Problem: data.js

let mArray = [];
...


function fillArray()
{
// hier wird mit **fetch** aus einer .xml gelesen und das Array gefüllt. Details spare ich mir der Übersichtlichkeit wegen.
Funktioniert aber, Array wird gefüllt.
}


function showArray()    // Testfunktion
{
    fillArray();
    console.log( mArray );     -> ok, Array gefüllt, funktioniert wie gewünscht
}

function getArray()    
{
    fillArray();
    return mArray;    - ist bei Aufruf leer!
}

jetzt die Übergabe aus 'data.js' -> 'display.js'

in display.js:

let nArray = [];
...
function showDataTable()
{
// Tabelle erstellen -> ok
nArray = getArray() -> Array.length hier ist immer 0! Liegt aber an 'fillArray();', da das Array erst nach dem Aufruf gefüllt wird.
}

Wo liegt genau der Fehler? Was übersehe ich?

--
Grüssle JustMe28 [X] Nail here for new Monitor
  1. Das Folgende funktioniert bei mir (in node). Ich vermute deshalb den Fehler außerhalb des Gezeigten.

    let mArray = [];
    
    
    function fillArray()
    {
        mArray=[ 1, 2, 3 ];
    }
    
    
    function showArray() {
    {
        fillArray();
        console.log( mArray );
    }
    
    function getArray()    
    {
        fillArray();
        return mArray;
    }
    
    fillArray();
    console.log( getArray() );
    Array2 = getArray();
    console.log( Array2 );
    showArray();
    

    Ausgaben:

    [ 1, 2, 3 ]
    [ 1, 2, 3 ]
    [ 1, 2, 3 ]
    

    Nachtrag:

    • Du hast das Zeug auf zwei Dateien verteilt. Ich habe das nicht getestet.

    • Möglicherweise/Wahrscheinlich hast Du falsche Vermutungen, wann das let mArray = []; ausgeführt wird. Werden die Variablen tatsächlich erst innerhalb der Funktion initialisiert, dann haben diese auch nur innerhalb der Funktion Gültigkeit.

    1. Nachtrag:

      • Du hast das Zeug auf zwei Dateien verteilt. Ich habe das nicht getestet.

      und genau das wird es sein.

      • Möglicherweise/Wahrscheinlich hast Du falsche Vermutungen, wann das let mArray = []; ausgeführt wird. Werden die Variablen tatsächlich erst innerhalb der Funktion initialisiert, dann haben diese auch nur innerhalb der Funktion Gültigkeit.

      Alle Variablen ausserhalb der Funktionen.

      Die Frage ist jetzt: wie bekomme ich es hin dass beim Aufruf der Funktion 'fillArray()' in data.js diese komplett!!! abgearbeitet wird?

      In der index.html wird die data.js vor der display.js geladen.

      Stand jetzt( Laden der index.html ):

      function fillArray()
      {
          fetch( dataFileName )
      	.then( function( response )    // Step-1
          {
              return response.text();  // hier wird die Funktion verlassen, Array.length = 0
      Wird in die display.js gewechselt, dort die Funktion 'showDataTable()', in der die Funktion getArray() aus der data.js aufgerufen wird. hier Array.lentgh logischerweise 0. 
      	})
      	.then( function( data )    // dann gehts wieder zurück in die data.js und es geht hier weiter. Danach ist das Array korrekt gefüllt.
          {
      // hier werden dann die Daten geladen.
      
      

      und das ist mein Problem 🤔

      ich meine es muss doch möglich sein aus einer .js Datei eine Funktion in einer anderen .js Datei, in der der Inhalt einer z. B. .xml Datei in ein Array geladen wird, aufzurufen und mit den Daten aus dem zurückgegebenen Array zu arbeiten?!

      Es geht hier "nur" um das komplette abarbeiten der Datenladefunktion und das return Array an die aufrufende Funktion( in 2 versch. .js ).

      --
      Grüssle JustMe28 [X] Nail here for new Monitor
      1. Von Prio "WICHTIG" auf "Interesse" heruntergestuft.

        Habe auf die html-Seite einen <Div>.addEventListener( "click" ... gesetzt, und bei Betätigung desselben läuft alles wie es soll.

        Wäre aber interessant wie so etwas beim ersten laden der Seite funktioniert.

        Aber bis hierhin erstmal Danke an Raketenwilli und alle anderen die helfen wollten.

        Schönes Wochenende an alle 😎

        --
        Grüssle JustMe28 [X] Nail here for new Monitor
        1. Und das geht auch:

          <html>
              <head>
                  <script src="test_fillArray.js"></script>
                  <script src="test_printArray.js"></script>
                  <script src="test_start.js"></script>
              </head>
              <body>
                  <hr><pre id="o1">Test</pre><hr><button id="p1">Klickmich!</button>
                  <script>
                      document.getElementById( "p1" ).addEventListener( "click", printArray );
                  </script>
              </body>
          </html>
          

          test_fillArray.js:

          function fillArray()
          {
          	mArray=[ 1, 2, 3 ];
          }
          

          test_printArray.js:

          function printArray()    
          {
              document.getElementById( "o1" ).innerHTML = JSON.stringify( mArray );
          }
          

          test_start.js

          let mArray=[];
          window.addEventListener('load',  fillArray );
          

          Ich will aber nicht verheimlichen, dass diese Vorgehensweise auf mich „befremdlich bis ungünstig“ wirkt. Dazu werden andere mehr auszuführen haben → und das ist schon geschehen.

        2. Habe auf die html-Seite einen <Div>.addEventListener( "click" ... gesetzt, und bei Betätigung desselben läuft alles wie es soll.

          Da Du mit einer globalen Variable arbeitest (so etwas krudes musste man anno 1990 in BASIC tun, in JS kann man die damit geradezu zwangsläufig verbundenen Irrtümer durch Aufruf parametrisierter Funktionen und Objektmethoden einfach vermeiden) wirst Du, im Hinblick auf Rolfs Ausführungen zum asynchronen fetch(), hierbei nicht mit der aktuellen sondern mit der vorherigen (alten) Antwort des Servers arbeiten.

          Das ist so, wie Du meinst, dass Du jetzt „frische Brötchen“ einkaufst, die dann aber irgendwo parkst und im Glauben an deren Frische die alten Brötchen aus dem Brotkasten isst. Die sind aber „Bäh!“

          • fetch(): hole neue Daten ... und schreibe nach Ankunft in Variable A

          • Lese jetzt Daten aus Variable A und schreibe diese ins Dokument.

          Es wird sofort - vor der Ankunft der neuen Daten - aus Variable A gelesen.

          Von Prio "WICHTIG" auf "Interesse" heruntergestuft.

          Das ist ein schwerer Fehler in der Programmlogik: Du hast zwar Daten, es sind aber nicht die erwarteten. Das merkst Du aber erst wenn Du in das nur vermeintlich frische Brötchen beißt.

          Wenn sich die Daten - oder der Request - hingegen nie ändern, dann hättest Du zwar korrekte Daten, aber was soll dann der wiederholte Request? Ändern sich die Daten (z.B. in der Datenbank) nicht, aber Parameter des Request dann hast Du in Deiner Variable zwar irgendwelche Daten - nur eben nicht diejenigen, die zum Request passen.

          Was Du willst ist:

          • fetch(): hole neue Daten und schreibe diese nach Ankunft ins Dokument.
          • (Der Umweg über die globale Variable ist gar nicht nötig)

          Ich selbst bin übrigens kein Freund davon, erst einmal eine leere Webseite zu liefern und dann endlose Reihen von solchen Requests zu starten um die auf der Webseite abzuholenden Inhalte abzuholen. Das Ergebnis solchen Tuns sind dann Webseiten, die erst mal erscheinen aber eben den erwarteten Inhalt nicht haben (und das eine ganze Weile lang, weil erst mal die mich nicht interessierende Werbung geladen wird, bzw. geladen werden soll) → was einen schnellen, reflexartigen Druck auf STRG+r nach sich zieht → wenn das selbe Zeug wieder kommt (das tut es dann), geht's zurück zur Suchmaschine.

          Besser ist es, den „Krempel“ (oder wenigstens die Daten) schon bei der Lieferung der Webseite mit zuliefern (und eventuell mit JS die Tabellen zu erzeugen - oder was immer Du vor hast). Auch Java-Script-Geraffel wie

          <script>
          var a=['foo', 'bar', 'baz'];
          </script>
          

          kann man auch mit PHP erzeugen:

          <?php
          $arr=['foo', 'bar', 'baz'];
          echo   '<script>'
               . PHP_EOL
               . "\t"
               . "let a=[ '"
               . implode( "', '", $arr )
               . "' ];"
               . PHP_EOL
               . '</script>'
          ;
          

          Erzeugt:

          <script>
          	let a=[ 'foo', 'bar', 'baz' ];
          </script>
          
          1. Hallo Raketenwilli,

            implode( "', '", $arr )
            

            ist ein Unfall, der darauf wartet, zu passieren.

            Wenn man genau weiß, dass in $arr keine ' Zeichen vorkommen können, kann man es riskieren, aber als allgemeines Code-Snippet ist es riskant. Bin gerade auf dem Sprung und habe die bessere Idee nicht fertig, aber mein Ansatz wäre, mit JSON-Strings zu arbeiten. Muss ich aber noch eine Weile dran hirnen.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hallo Raketenwilli,

              implode( "', '", $arr )
              

              ist ein Unfall, der darauf wartet, zu passieren.

              Wenn man genau weiß, dass in $arr keine ' Zeichen vorkommen können, kann man es riskieren, aber als allgemeines Code-Snippet ist es riskant. Bin gerade auf dem Sprung und habe die bessere Idee nicht fertig, aber mein Ansatz wäre, mit JSON-Strings zu arbeiten. Muss ich aber noch eine Weile dran hirnen.

              Rolf

              Hatte ich schon fertig :-) … weil mir in „Nullkommanix“ nach dem Absenden klar war, dass ich so umständlich wie idotisch notiert hatte.

              <?php
              $arr=['foo', 'bar"]', 'baz'];
              echo  
                     '<script>'
                   . PHP_EOL
                   . "\t"
                   . 'let a='
                   . json_encode( $arr )
                   . ';'
                   . PHP_EOL
                   . '</script>'
              ;
              

              Output:

              <script>
              	let a=["foo","bar\"]","baz"];
              </script>
              

              Regel für den Einsatz: Immer sauber bei UTF-8 bleiben.

              1. Hallo,

                Output:

                <script>
                	let a=["foo","bar\"]","baz"];
                </script>
                

                Regel für den Einsatz: Immer sauber bei UTF-8 bleiben.

                nicht der schlechteste Rat - hier im Beispiel aber egal, weil nur ASCII-Zeichen vorkommen.

                Einen schönen Tag noch
                 Martin

                --
                Windows ist manchmal echt witzig. Vor einiger Zeit erlebt:
                "Die Problembehandlung kann aufgrund eines Problems nicht gestartet werden."
              2. Jetzt hat mir der Martin das Update unmöglich gemacht…

                <?php
                $arr=[ 'foo', 'bar"]', 'baz', 'Jörg' ];
                ?>
                <script>
                   let arr=<?=json_encode( $arr, JSON_UNESCAPED_UNICODE ); ?>;
                   console.log( arr );
                </script>
                

                <script>
                	let arr=["foo","bar\"]","baz","Jörg"];
                	console.log( arr );
                </script>
                

                [ 'foo', 'bar"]', 'baz', 'Jörg' ]
                
                1. Jetzt hat mir der Martin das Update unmöglich gemacht…

                  <?php
                  $arr=[ 'foo', 'bar"]', 'baz', 'Jörg' ];
                  ?>
                  <script>
                     let arr=<?=json_encode( $arr, JSON_UNESCAPED_UNICODE ); ?>;
                     console.log( arr );
                  </script>
                  

                  <script>
                  	let arr=["foo","bar\"]","baz","Jörg"];
                  	console.log( arr );
                  </script>
                  

                  [ 'foo', 'bar"]', 'baz', 'Jörg' ]
                  

                  Das Einschmuggeln von HTML/weiterem Javascript muss entweder vorher (in PHP) oder (weil erst dann der Kontext bekannt ist: nachher) im Javascript geschehen. <, > zu ersetzen dürfte oft reichen allerdings kann es sein, dass auch ' oder " durch Entities ersetzt werden müssen.

      2. Hi,

        • Du hast das Zeug auf zwei Dateien verteilt. Ich habe das nicht getestet.

        und genau das wird es sein.

        ist denn die zweite Datei zu dem Zeitpunkt, zu dem eine Funktion aus ihr aufgerufen wird, bereits geladen?

        cu,
        Andreas a/k/a MudGuard

  2. Hallo JustMe28,

    fetch ist asynchron. Es kehrt sofort zurück. Die Daten stehen erst zur Verfügung, wenn der then-Handler aufgerufen wird.

    Deine showArray-Funktion kann deshalb eigentlich nicht funktionieren, es sei denn, die Arraydarstellung, die der Browser in die Konsole schreibt, wird in der Konsole bei nachträglichen Änderungen aktualisiert. Keine Ahnung, käme mir komisch vor.

    Korrekt wäre es, das fetch-Promise aus der fillArray Funktion zurückzugeben und darauf einen neuen then-Handler zu setzen, so dass das asynchrone Konzept durchgehalten wird. Das kann man unter einem Haufen Syntaxzucker verschütten, mit dem async-await Muster, aber ich weiß nicht, ob ich Dir das zumuten kann.

    function fillArray(url) {
       return fetch(url)
              .then(response => response.json())
              .then(data => {
                 let array = [];
                 // Array aus data-response aufbauen
                 // UND ZURÜCKGEBEN. KEINE GLOBALE VARIABLE VERWENDEN!
                 return array;   
              });
    }
    

    Um diesen Code wirklich zu verstehen, muss man Promises durchschauen. Die fetch-Funktion schickt den HTTP Request an die genannte URL und kehrt dann mit einem Promise A zurück. Auf diesem Promise wird die erste then-Methode aufgerufen, um eine Funktion zu registrieren, die das Ergebnis des fetch-Aufrufs verarbeiten soll. Das ist dieses response => response.json(). Es ist eine Pfeilfunktion, die nichts weiter tut, als auf dem response-Objekt die json-Methode aufzurufen und das Ergebnis der json-Methode zurückzugeben.

    Aus then kommt ein neues Promise B zurück. Im einfachsten Fall erfüllt sich B, wenn A erfüllt ist und die mit dem ersten then registrierte Funktion einen einfachen Wert zurückgibt. Das ist hier aber nicht der Fall, denn response.json() gibt seinerseits ein Promise C zurück. Das geschieht, weil der Datenstrom vom Server in dem Moment, wo der erste then-Handler läuft, noch gar nicht fertig gelesen ist. Das passiert erst innerhalb von json().

    Der Umstand, dass die Funktion im ersten then das Promise C zurückgibt, führt dazu, dass JavaScript Promise B mit Promise C verknüpft. Sobald C sind erfüllt und einen Wert bereitstellt, erfüllt sich auch B.

    Darauf wird mit dem zweiten then reagiert. Hier wird eine Funktion hinterlegt, in der die von json() ermittelten Daten verarbeitet werden. Dieses zweite then gibt wiederum ein Promise D zurück, das sich nach den gleichen Regeln erfüllt wie Promise B.

    Beachte das return vor dem fetch. Es gibt den Wert zurück, der sich aus dem vollständigen Ausdruck dahinter ergibt, also fetch(...).then(...).then(...). Der Wert dieses Ausdrucks ist das Promise, das vom zweiten then geliefert wird, also das Promise D. Das geht an den Aufrufer von fillArray zurück, und der kann nun damit wieder weiterarbeiten.

    function showArray() {
       fillArray(url)
       .then(array => {
          // Jetzt steht das Array sicher zur Verfügung und 
          // kann verarbeitet werden
       });
    }
    

    Wenn Du meinst, dass Du es unbedingt musst, kannst Du an dieser Stelle das array-Argument in der globalen Variablen speichern.

    Noch kurz zu async-await. Das ist ein Syntaxzucker um Promises herum, und man könnte fillArray und showArray damit auf diese Weise aufbauen:

    async function getArray(url) {
       let response = await fetch(url);
       let jsonData = await response.json();
       let array = [];
       // Array aus jsonData füllen
       return array;
    }
    
    function showArray(url) {
       getArray(url)
       .then(array => {
          // verarbeiten
       });
    }
    // ODER
    async function showArray(url) {
       array = await getArray(url);
       // array verarbeiten
    }
    

    await ist nur in async-Funktionen zulässig. Wesentliche Eigenschaft von async-Funktionen ist, dass sie ihr Ergebnis grundsätzlich als Promise zurückliefern und nicht in dem Moment ausgeführt werden, wo man sie aufruft, sondern in die Mikrotask-Queue eingestellt werden. Was in der Mikrotask-Queue steht, wird erst dann ausgeführt, wenn der eigentliche JavaScript-Aufruf fertig ist und der Browser bereit für eine Anzeigeaktualisierung wäre.

    Deswegen muss man genau überlegen, ob es sinnvoll ist, eine Funktion async zu machen oder nicht. Vor allem, wenn man mit globalen Variablen hantiert, führt das zumeist zum Chaos, weil die Funktion nicht dann läuft, wenn man sie aufruft, sondern erst als Mikrotask. Aber das ist bei allem, was mit Promises zu tun hat, so.

    Rolf

    --
    sumpsi - posui - obstruxi
    1. Um diesen Code wirklich zu verstehen, muss man Promises durchschauen.

      Und dazu wissen, dass diese „Promises“ im Kern und also abseits des beliebten Buzzword-Usings nur so etwas wie „event-handler“ sind.

      Statt eines Buttons als Objekt eben das fetch und statt des click eben der Eingang der Antwort vom Server (bzw. auch der Timeout).

      Anders ausgedrückt, der Prozess (ein Typ im grauen Kittel) steckt eine Nachricht in die Rohrpostanlage und winkt einen weiteren Typ im grauen Kittel herbei, dem er mitteilt, was dieser zu tun hat wenn die Antwort kommt. Sobald der zweite durch Nicken anzeigt, verstanden zu haben, eilt der erste weiter und erledigt - ohne „zurückzuschauen“ - seine übrigen Aufgaben.

      Wieso man das „Promise“ („Versprechen“) nennt steht in den Sternen. Es wäre eher eine „Auftragsvergabe ohne Überprüfung des Ergebnisses“, oder „Auftrag vergeben und vergessen“ also ein „Subcontracting without checking the result“ oder „Make a subcontract and forget“.

      1. Hallo Raketenwilli,

        fetch ist genauso asynchron wie XmlHttpRequest, nur dass man beim XHR die klassische EventTarget-Schnittstelle verwendet und bei fetch die Promise-Schnittstelle.

        Beide sind asynchron, beide sind im Moment des Sendens "fire and forget", beide bekommen ein Signal wenn der Request fertig oder fritte ist.

        Der Unterschied zwischen Promise und EventTarget ist, dass Promises einfacher zu implementieren sind. Schreib mal selbst ein Objekt, das EventTarget implementiert - gar nicht so einfach, die addEventListener, removeEventListener und dispatchEvent Methoden korrekt zu bauen. Natürlich geht es - aber es gibt eben keinen fertigen Baukasten dafür. Promises schenken Dir das, und verpacken einen Teil der Komplexität.

        Events können grundsätzlich mehr. Ein Promise resolved einmal und ist dann fertig, während Events beliebig oft feuern können. Aber die Einschränkung des Promise bedeutet auch eine einfachere Handhabung. Hinzu kommt, dass - vermute ich zumindest - Promises leichtgewichtiger sind. Ein erfülltes oder zurückgewiesenes Promise wird in der Microtask-Queue verarbeitet, während ein Event über die Eventqueue läuft. Ich bin nicht sicher, aber ich meine, dass die Eventqueue nach jedem Event erstmal eine Layout-Phase einschiebt, während die Microtask-Queue das nicht tut.

        Und versuch mal, mit Events eine Verkettung hinzubekommen. Die Reihenfolge der Eventhandler eines Events ist nicht definiert. Aber eine Promise.then.then... Kette ist wohldefiniert. Genauso kompliziert ist es, eine Gruppe von nebenläufigen Aktionen zu koordinieren. Den Effekt von Promise.all mit Events nachzubauen ist sicher möglich, aber man muss es eben erstmal tun.

        Beides hat seinen Sinn. Für eine nachvollziehbar gesteuerte Nebenläufigkeit sind Promises besser. Das Konzept ist - unter dem Namen 'Futures' - übrigens älter als JavaScript und in etlichen Sprachen verfügbar. In C# zum Beispiel über die Task-Klasse. Und ich kann sowohl in C# wie auch in JavaScript die Promises mit async/await überzuckern. Mit Events geht das nicht.

        Rolf

        --
        sumpsi - posui - obstruxi
        1. Ein erfülltes oder zurückgewiesenes Promise wird in der Microtask-Queue verarbeitet, während ein Event über die Eventqueue läuft. Ich bin nicht sicher, aber ich meine, dass die Eventqueue nach jedem Event erstmal eine Layout-Phase einschiebt, während die Microtask-Queue das nicht tut.

          Alles gut Rolf. Wir verfolgen nur verschiedende Ansätze:

          Ich erkläre sowas gern Leuten, von denen ich glaube, dass sind die selben Sorte „Idioten“ wie meinereiner selbst… und vermeide dabei also Begriffe, bei deren Kenntnis der Empfänger eigentlich schon wissen müsste, was ich ihm gerade erklären will.

          Ein Promise resolved einmal

          Hm. Was ist mit setTimeout(), vor allem aber windows.setInterval()? Für mich sind das auch nur „Typen im grauen Kittel“, die „herbeigewunken und im Zusammenhang mit einem Ereignis (soll jemand auf die Uhr sehen, dann loslegen) mit einer Aufgabe betraut“ werden. Beide Funktionen werden im Web auf seriös aussehenden Seiten im Zusammenhang mit Promises genannt.

          1. Hallo Raketenwilli,

            Beide Funktionen werden im Web auf seriös aussehenden Seiten im Zusammenhang mit Promises genannt

            Hä? Hast du ein Beispiel?

            setTimeout kann man in ein Promise einpacken, hab ich auch schon gemacht. Bei setInterval ist das Unfug.

            Rolf

            --
            sumpsi - posui - obstruxi
            1. Hallo Raketenwilli,

              Beide Funktionen werden im Web auf seriös aussehenden Seiten im Zusammenhang mit Promises genannt

              Hä? Hast du ein Beispiel?

              https://www.google.com/search?q=setTimeout()%2C+windows.setInterval()+Promise

              (Absichtlich kein Link. Hier weil manche Browser diese gern vorab in den Cache laden und google dann denkt, der Benutzer am Gerät mit dem Token „gajcdg6asd576a5sdsadh“ weiß das nicht.)

              Reicht die Liste?

              1. Hallo Raketenwilli,

                da steht an mehreren Stellen deutlich, dass setInterval sich nicht in ein Promise umbauen lässt. Weil ein Promise nur einmal resolved.

                Mit setTimeout geht das, weil setTimeout nur einmal feuert:

                function delay(millisecs, data) {
                   return new Promise((function(resolve,reject) {
                      setTimeout(resolve, millisecs, data);
                   });
                }
                
                delay(2000, "Hallo")
                .then(huhu => console.log(huhu));
                

                gibt nach 2s "Hallo" aus.

                SetInterval könnte man über einen asynchronen Generator realisieren, steht da, aber alle Beispiele verwenden unter der Haube setTimeout um zum nächsten Schritt zu kommen - mit allen Nachteilen. Mit setInterval bekommt man glattere Zeitabstände - aber man kann den callback von setInterval nicht auf ein Promise mappen.

                Aber ob ich mir hier jetzt mit einem Beispiel für einen asynchronen Generator Freude mache?

                Denkbares Szenario: Man verwendet einen Intervallgeber, der von 1 bis 50 ticken soll, in 500ms Abständen. Diese 50 Werte möchte man konsumieren, aber NICHT mit einem setInterval-Callback, sondern eingebettet in eine andere Verarbeitung, d.h. man möchte auf den Tick warten, dann möchte man etwas tun, und wieder auf den Tick warten. Als Komplikation könnte man ergänzen, dass dieses "etwas tun" mal länger und mal kürzer dauert, und auch mal länger dauern kann als der Abstand zwischen zwei Ticks, und in dem Fall sollen die "ausgelassenen Ticks" möglichst schnell nachgeholt werden.

                Es wäre doch schick, wenn die Verarbeitung ganz stumpf so aussehen könnte:

                for (let seq of sequenceGenerator(1,50) {
                   // do something with seq
                }
                

                Und ja, das geht. Man muss noch etwas ergänzen:

                for await (let seq of sequenceGenerator(1,50) {
                   // do something with seq
                }
                

                Und nun kann man den sequenceGenerator als asynchronen Generator implementieren.

                async function* sequenceGenerator(start, end) {
                   // ...some magic control
                   yield counter;
                }
                

                Im Inneren des sequenceGenerators kann man mit setTimeout arbeiten, um die Ticks abzuwarten, aber dann hat man ggf. zeitliche Unregelmäßigkeiten. Besser ist setInterval.

                Das Beispiel steht hier: https://jsfiddle.net/Rolf_b/raLz483h/

                Ich muss aber jetzt weg vom Gerät, eine Erklärung folgt später.

                Rolf

                --
                sumpsi - posui - obstruxi
              2. Hallo Raketenwilli,

                natürlich muss man, bevor man sowas baut, die Frage stellen, ob es überhaupt sinnvoll ist. Normalerweise gibt's einen Tick, man tut was am UI und dann ist es wieder gut.

                D.h. setInterval ist eher ein schlechtes Beispiel für einen asynchronen Generator. Besser wäre vermutlich das blockweise Einlesen einer Datei (die I/O ist asynchron und erzeugt Promises) oder eine Schleife über das wiederholte FETCHen irgendwelcher Daten.

                Rolf

                --
                sumpsi - posui - obstruxi