Ich arbeite an einem Musikprogramm, bei dem mehrere Javascript-Elemente mit einem anderen synchron sein müssen. Ich habe setInterval verwendet, das anfangs sehr gut funktioniert, aber im Laufe der Zeit werden die Elemente allmählich nicht mehr synchron, was mit einem Musikprogramm schlecht ist.
Ich habe online gelesen, dass setTimeout genauer ist, und Sie können setTimeout-Schleifen irgendwie haben, aber ich habe keine generische Version gefunden, die veranschaulicht, wie dies möglich ist. Könnte mir jemand ein einfaches Beispiel für die Verwendung von setTimeout zeigen, um etwas auf unbestimmte Zeit zu schleifen.
Danke dir. Wenn es alternativ möglich ist, mit setInterval oder einer anderen Funktion synchronere Ergebnisse zu erzielen, lassen Sie es mich bitte wissen.
BEARBEITEN:
Grundsätzlich habe ich einige Funktionen wie diese:
//drums
setInterval(function {
//code for the drums playing goes here
},8000);
//chords
setInterval(function {
//code for the chords playing goes here
},1000);
//bass
setInterval(function {
//code for the bass playing goes here
},500);
Es funktioniert anfangs super gut, aber im Laufe von ungefähr einer Minute werden die Sounds merklich nicht mehr synchron, da ich gelesen habe, dass dies mit setInterval geschieht. Ich habe gelesen, dass setTimeout konsistenter genau sein kann.
quelle
setTimeout
Sie können berechnen, wie lange die Verzögerung tatsächlich gedauert hat, um die Zeit für das nächste Timeout anzupassen.requestAnimationFrame
? Sie müssen nur die Zeit angeben, zu der das Audio bei jedemrequestAnimationFrame
Rückruf ausgeführt wird.Antworten:
Sie können eine
setTimeout
Schleife mithilfe der Rekursion erstellen :Das Problem mit
setInterval()
undsetTimeout()
ist, dass es keine Garantie gibt, dass Ihr Code in der angegebenen Zeit ausgeführt wird. IndemsetTimeout()
Sie es rekursiv verwenden und aufrufen, stellen Sie sicher, dass alle vorherigen Vorgänge innerhalb des Zeitlimits abgeschlossen sind, bevor die nächste Iteration des Codes beginnt.quelle
setInterval
?setInterval()
erneuten Ausführung nicht abgeschlossen sind , können Ihre Variablen und / oder Daten sehr schnell nicht mehr synchron sein. Wenn ich zum Beispiel nach Daten suche und der Server länger als 1 Sekunde braucht, um zu antworten, hätte die VerwendungsetInterval()
meiner vorherigen Daten die Verarbeitung nicht abgeschlossen, bevor mein nächster Vorgang fortgesetzt wurde. Bei diesem Ansatz kann nicht garantiert werden, dass Ihre Funktion jede Sekunde gestartet wird. Es ist jedoch garantiert, dass Ihre vorherigen Daten vor Beginn des nächsten Intervalls vollständig verarbeitet wurden.Nur zur Ergänzung. Wenn Sie eine Variable übergeben und iterieren müssen, können Sie dies wie folgt tun:
Ausgabe:
Eine Zeile pro Sekunde.
quelle
Da keine der beiden Zeiten sehr genau sein wird, besteht eine Möglichkeit,
setTimeout
etwas genauer zu sein, darin, zu berechnen, wie lange die Verzögerung seit der letzten Iteration gedauert hat, und dann die nächste Iteration entsprechend anzupassen. Beispielsweise:Wenn Ihr Code also zum ersten Mal (mindestens) 1000 ms wartet, wenn er ausgeführt wird, ist es möglicherweise etwas spät, z. B. 1046 ms. Wir subtrahieren also 46 ms von unserer Verzögerung für den nächsten Zyklus und die nächste Verzögerung ist nur 954 ms. Dies verhindert nicht, dass der Timer zu spät ausgelöst wird (was zu erwarten ist), hilft Ihnen jedoch dabei, das Auffüllen der Verzögerungen zu verhindern. (Hinweis: Möglicherweise möchten Sie überprüfen, ob
thisDelay < 0
die Verzögerung mehr als doppelt so hoch war wie Ihre Zielverzögerung, und Sie haben einen Zyklus verpasst - bis zu Ihnen, wie Sie mit diesem Fall umgehen möchten.)Dies wird Ihnen wahrscheinlich nicht helfen, mehrere Timer synchron zu halten. In diesem Fall möchten Sie vielleicht herausfinden, wie Sie sie alle mit demselben Timer steuern können.
Wenn Sie sich also Ihren Code ansehen, sind alle Ihre Verzögerungen ein Vielfaches von 500, sodass Sie so etwas tun können:
quelle
Der beste Weg, um mit dem Audio-Timing umzugehen, ist mit der Web-Audio-API. Sie verfügt über eine separate Uhr, die genau ist, unabhängig davon, was im Haupt-Thread passiert. Hier gibt es eine großartige Erklärung, Beispiele usw. von Chris Wilson:
http://www.html5rocks.com/de/tutorials/audio/scheduling/
Schauen Sie sich auf dieser Website nach weiteren Web-Audio-APIs um. Sie wurde entwickelt, um genau das zu tun, wonach Sie suchen.
quelle
setTimeout
reichen von unzureichend bis schrecklich überkomplex. Die Verwendung einer nativen Funktion scheint eine viel bessere Idee zu sein. Wenn die API Ihren Zweck nicht erfüllt, würde ich empfehlen, nach einer zuverlässigen Planungsbibliothek von Drittanbietern zu suchen.Verwenden
setInterval()
Das obige wird
alert("Hello");
alle 3 Sekunden ausgeführt.quelle
Ich benutze diesen Weg im Arbeitsleben: "Vergiss gemeinsame Schleifen" in diesem Fall und benutze diese Kombination von "setInterval" beinhaltet "setTimeOut" s:
PS: Verstehe, dass das wirkliche Verhalten von (setTimeOut): Sie werden alle zur gleichen Zeit starten "Die drei bla bla bla werden im selben Moment herunterzählen", also mache eine andere Zeitüberschreitung, um die Ausführung zu arrangieren.
PS 2: Das Beispiel für eine Zeitschleife, aber für eine Reaktionsschleife können Sie Ereignisse verwenden, versprechen asynchrones Warten.
quelle
quelle
Entsprechend Ihrer Anforderung
Wir haben folgendes Beispiel, das Ihnen helfen kann
quelle
quelle
Wie bereits erwähnt, verfügt die Web-Audio-API über einen besseren Timer.
Aber wenn diese Ereignisse konsistent auftreten, wie wäre es dann, wenn Sie sie alle auf den gleichen Timer setzen? Ich denke darüber nach, wie ein Step-Sequenzer funktioniert.
Könnte es praktisch so aussehen?
quelle
Ich denke, es ist besser, am Ende der Funktion eine Zeitüberschreitung zu verursachen.
Diese drei Funktionen sind erforderlich, da Variablen in der zweiten Funktion jedes Mal mit dem Standardwert überschrieben werden. Wenn der Programmzeiger das setTimeout erreicht, ist bereits ein Schritt berechnet. Dann braucht nur der Bildschirm etwas Zeit.
quelle
Verwenden Sie let anstelle von var im Code:
quelle