2016-12-10 1 views
0

Ich versuche asynchrone Tests in einer synchronen Reihenfolge auszuführen. Das heißt, jeder Test muss Dateien laden und ist somit per Definition nicht synchron - stattdessen möchte ich darauf warten, dass jeder Test seine Dateien lädt, Code ausführt und erst dann zum nächsten Test geht und seine Dateien usw. lädt.Schließung speichert keine lokalen Variablen

Das Problem - sehr seltsam, bekomme ich eine Schließung, die die Werte der lokalen Variablen nicht richtig außerhalb davon hält.

Dieses Snippet ist Teil einer größeren Bibliothek, daher kann ich kein autarkes Beispiel geben, das Sie ausführen können, aber die Logik hier ist ziemlich einfach.

let viewer = ...; 
let tests = [...]; // Let's say the length is 3 

function runTestSync(callback, index) { 
    console.log("FIRST", index) 

    if (index >= tests.length) { 
     callback(index, true); 
    } else { 
     let entry = tests[index]; 

     // Results in files being loaded 
     entry[1](viewer); 

     // Add an event listener to the "viewer" object, which will eventually call the callback when all files finished loading 
     viewer.addEventListener("loadend", function listener() { 
      if (viewer.resourcesLoading === 0) { 
       console.log("SECOND", index); 

       viewer.removeEventListener(listener); 

       callback(index, false); 
      } 
     }); 
    } 
} 

function myIter(index, done) { 
    if (!done) { 
     runTestSync(myIter, index + 1); 
    } 
} 

runTestSync(myIter, 0); 

Dies ist die einfachste synchrone Schleife, die asynchrone Serverabrufe verwendet. Ich glaube, Sie können vereinbaren, dass schließlich diese Zeilen gedruckt werden sollen:

FIRST 0 
SECOND 0 
FIRST 1 
SECOND 1 
FIRST 2 
SECOND 2 

Was passiert stattdessen?

FIRST 0 
SECOND 0 
FIRST 1 
SECOND 0 
FIRST 1 
SECOND 0 
FIRST 1 
... 

Und ich bekomme eine Endlosschleife. Warum ist der zweite Zugriff auf index immer gleich 0? Dies ist eindeutig die Art und Weise, wie Schließungen funktionieren sollen.

+0

Ihr Code fügt Ereignishandler immer wieder zum selben Objekt hinzu. Es ist schwer zu sagen, was vor sich geht, ohne den Code für das zu sehen, was diese "Betrachter" -Sache ist. – Pointy

+0

Sie sollten die erste von Ihnen gepostete Frage löschen und den Link zu dieser Frage entfernen. –

+0

Danke, habe nicht realisiert, dass ich Fragen löschen kann. Der Event-Handler entfernt sich selbst, daher gibt es immer nur einen zu einem Zeitpunkt. Das Viewer-Objekt ist ziemlich groß, aber es ist eigentlich nicht mit diesem Code verwandt - egal, wie das Viewer-Objekt Dateien lädt oder was es dazwischen tut - der Punkt ist, dass ich in derselben Funktion nur auf eine lokale Variable zugreifen kann gut, aber wenn es in einer Schließung in der gleichen Funktion ist, hat es plötzlich einen anderen Wert? – user2503048

Antwort

0

Ich habe vergessen, den Typ des zu entfernenden Listeners bei viewer.removeEventListener(TYPE, listener) hinzuzufügen. Das waren 10 Stunden, die ich nicht zurückbekomme.

Verwandte Themen