DOM-refresh auf die lange Laufzeit-Funktion
Habe ich eine Schaltfläche, die führt eine lange andauernde Funktion, wenn es angeklickt wird. Jetzt, während die Funktion ausgeführt wird, das will ich ändern den text der Schaltfläche, aber ich habe Probleme in einigen Browsern wie Firefox, IE.
html:
<button id="mybutt" class="buttonEnabled" onclick="longrunningfunction();"><span id="myspan">do some work</span></button>
javascript:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
document.getElementById("mybutt").disabled = true;
document.getElementById("mybutt").className = "buttonDisabled";
//long running task here
document.getElementById("myspan").innerHTML = "done";
}
Jetzt hat diese Probleme in firefox und IE, ( in chrome funktioniert es ok )
So, ich dachte, um es in ein settimeout:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
document.getElementById("mybutt").disabled = true;
document.getElementById("mybutt").className = "buttonDisabled";
setTimeout(function() {
//long running task here
document.getElementById("myspan").innerHTML = "done";
}, 0);
}
aber das funktioniert nicht, entweder für firefox!!! wird der button deaktiviert, wechselt die Farbe ( aufgrund der Anwendung des neuen css ) aber der text ändert sich nicht.
Habe ich die Zeit auf 50ms statt nur 0ms, um zu machen, arbeiten ( ändern Sie die Schaltfläche text ). Jetzt finde ich diese blöde zumindest. Ich kann verstehen, wenn es funktionieren würde-nur mit 0ms Verzögerung, aber was passieren würde, in einem langsameren computer? vielleicht firefox müsste 100ms es in der settimeout? es klingt eher dumm. Ich habe versucht, viele Male, 1ms, 10ms, 20ms...Nein, es wird nicht aktualisiert. nur mit 50ms.
Also folgte ich dem Rat in diesem Thema:
Zwingt einen DOM aktualisieren in Internet explorer nach der javascript dom-manipulation
also habe ich versucht:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
var a = document.getElementById("mybutt").offsetTop; //force refresh
//long running task here
document.getElementById("myspan").innerHTML = "done";
}
aber es funktioniert nicht ( FIREFOX 21). Dann habe ich versucht:
function longrunningfunction() {
document.getElementById("myspan").innerHTML = "doing some work";
document.getElementById("mybutt").disabled = true;
document.getElementById("mybutt").className = "buttonDisabled";
var a = document.getElementById("mybutt").offsetTop; //force refresh
var b = document.getElementById("myspan").offsetTop; //force refresh
var c = document.getElementById("mybutt").clientHeight; //force refresh
var d = document.getElementById("myspan").clientHeight; //force refresh
setTimeout(function() {
//long running task here
document.getElementById("myspan").innerHTML = "done";
}, 0);
}
Ich sogar versucht, clientHeight statt offsetTop aber nichts. das DOM nicht aktualisiert.
Kann jemand bieten eine zuverlässige Lösung vorzugsweise nicht-hacky ?
vielen Dank im Voraus!
als die hier vorgeschlagen werden, ich habe auch versucht
$('#parentOfElementToBeRedrawn').hide().show();
ohne Erfolg
Kraft-DOM neu zeichnen/aktualisieren auf Chrome/Mac
TL;DR:
suchen eine ZUVERLÄSSIGE cross-browser-Methode, um eine erzwungene DOM aktualisieren, OHNE die Verwendung von setTimeout (bevorzugte Lösung aufgrund von unterschiedlichen Abständen benötigt, abhängig von der Art von lange das ausführen von code, browser -, computer-Geschwindigkeit und setTimeout erfordert überall von 50 bis 100 MS je nach situation)
jsfiddle: http://jsfiddle.net/WsmUh/5/
ja, ich habe gerade meinen Beitrag aktualisiert mit einem jsfiddle.
Mit Bezug auf deinen edit, bedeutet dies, jQuery können auch Teil der Lösung sein?
mybutt
er erSie wollen nicht zu haben, schwere Verarbeitung in Ihrem Haupt-browser-thread, wie es friert die Seite. Die Verwendung von Web-Arbeiter, um die Aufgabe auszuführen.
InformationsquelleAutor MirrorMirror | 2013-06-01
Du musst angemeldet sein, um einen Kommentar abzugeben.
ES GELÖST!! Keine setTimeout()!!!
Getestet in Chrome 27.0.1453, Firefox 21.0, Internet 9.0.8112
DEMO HIER!
Dadurch wird die standard-browser-Verhalten. Klicken Sie auf Ereignisse nicht ausgelöst, bis nach einem mousedown-und mouseup-Feuer für das gleiche element. Wenn entweder Auftritt, während Sie die Maus außerhalb des Elements, das click-Ereignis nicht ausgelöst. Problematische Anwendungsfälle: 1) Drücken Sie die Maus-Taste, während Sie innerhalb des Elements, bewegen Sie die Maus außerhalb, dann die Taste loslassen. Die animation läuft auf unbestimmte Zeit, aber die Verarbeitung startet nie. 2) Drücken Sie die Maus-Taste, während Sie außerhalb des Elements, bewegen Sie die Maus nach innen, dann die Taste loslassen. Die Verarbeitung läuft mit keinen sichtbaren Hinweis, dass es gestartet wird.
Gut........leider für den OP, er will etwas, ohne setTimeout ().......dies ist die EINZIGE Lösung, die ich ausprobiert 34 verschiedenen Iterationen, und das ist die, die den test bestanden haben. Es sei denn, er ist bereit, zu verwenden, setTimeout(), oder betteryet, verwenden Sie ein WebWorker..die ist auf jeden Fall, wie ich es tun würde.......dies ist die eine für ihn. Wenn das bewegen der Maus aus der Schaltfläche ein Thema ist, schlage ich vor, er macht den Knopf extra large. 🙂
vielen Dank für deine Antwort, ich werde versuchen, um zu sehen, ob ich vermeiden kann, den problematischen Fällen, wie bereits von Matt. Ich bin nicht dagegen, eine setTimeout-Lösung per se, ich bin fein mit einer Lösung mit setTimeout(..., 0) oder setTimeout(...,1), was ich nicht will ist, setTimeout(..., 50/100), wo müsste ich legte großen Wert zu kümmern, die für alle Browser
aber intern jquery verwendet, setTimeout alles vorbei -.- du bist nur mit einem Rahmen statt, ich sehe nicht, was ist smart in diesem
InformationsquelleAutor Kylie
Webseiten werden aktualisiert, basierend auf einer single-thread-controller, und die Hälfte der Browser nicht aktualisieren Sie die DOM-oder styling bis Ihre JS Ausführung hält, was rechnerische Kontrolle an den browser zurück. Das heißt, wenn Sie einige
element.style.[...] = ...
es nicht treten in bis Sie Ihren code Ausführung beendet ist (entweder komplett, oder, weil der browser sieht, dass du etwas tust, kannst es abfangen der Verarbeitung für ein paar ms).Haben Sie zwei Probleme: 1) die Taste hat eine
<span>
. Entfernen, setzen Sie einfach .innerHTML auf die Schaltfläche selbst. Aber das ist nicht das eigentliche problem natürlich. 2) man läuft sehr lange Operationen, und Sie sollten denken sehr intensiv darüber nach, warum, und nach der Antwort auf das warum, wie:Wenn Sie eine lange computational job ist, schneiden Sie es bis in die timeout-Callback (oder, im Jahr 2019, await/async - siehe Hinweis am Ende dieses anser). Ihre Beispiele zeigen nicht, was Ihre "long job" eigentlich ist (ein spin-Schleife zählt nicht), aber Sie haben mehrere Optionen, je nach Browser, den Sie nehmen, mit einem RIESEN booknote: laufen Sie nicht lange jobs in JavaScript, Zeitraum. JavaScript ist eine single-threaded-Umgebung, die von der Spezifikation, so dass jede operation, die Sie tun möchten, sollten in der Lage sein, in Millisekunden. Wenn es nicht, Sie sind buchstäblich etwas falsch zu machen.
Wenn Sie brauchen, um zu berechnen, schwierige Dinge, auslagern auf den server mit AJAX-Bedienung (universal Browsern, oft geben Sie eine) schnellere Verarbeitung für diesen Vorgang und b) eine gute 30 Sekunden Zeit, Sie können nicht asynchron-das Ergebnis warten, zurückgegeben zu werden) oder verwenden Sie ein webworker hintergrund-thread (sehr viel NICHT universal).
Wenn Ihre Berechnung dauert lange, aber nicht so absurd, umgestalten von code, so dass Sie durchführen, Teile, mit timeout-Atempause:
Einer langen Berechnung kann fast immer umgestaltet werden, in mehreren Schritten, entweder, weil Sie die Durchführung mehrerer Schritte, oder weil Sie die gleiche Berechnung eine million mal, und kann schneiden Sie es in batches. Wenn Sie (übertrieben):
dann können Sie trivial schneiden Sie diese in ein timeout-entspannt-Funktion mit einem callback -
TL;DR: laufen Sie nicht lange Berechnungen, aber wenn Sie zu haben, damit der server die Arbeit für Sie tun und benutzen Sie einfach einen asynchronen AJAX-Aufruf. Der server kann die Arbeit schneller, und Ihre Seite nicht blockieren.
JS-Beispiele, wie man mit langen Berechnungen in JS auf dem client sind nur hier, um zu erklären, wie Sie mit diesem problem umzugehen, wenn Sie nicht die Möglichkeit haben, zu tun, AJAX-calls, die 99,99% der Zeit nicht der Fall sein.
Bearbeiten
beachten Sie auch, dass Ihr bounty-Beschreibung ist das ein klassischer Fall von Die XY-problem
2019 Bearbeiten
In der modernen JS der " await/async-Konzept verbessert auf timeout Rückrufe, so verwenden Sie diese statt. Alle
await
lässt der browser weiß, dass es sicher ausführen von geplanten updates, so dass Sie Ihren code schreiben, in einem "strukturierten, als ob es synchron" Weg, aber Sie markieren Sie Ihre Funktionen alsasync
, und dann Sieawait
Ihre Ausgabe Wann auch immer Sie Sie nennen:ich werde wahrscheinlich teilen Sie die lange Ausführungszeit der Funktion in kleinen settimeouts
Das könnte klug sein; wenn es nicht geht auf dem server, dann schneiden Sie Sie in eine callback-Kette mit timeouts mindestens unblock-browser.
Btw, hast du dir in Webworker, weil das klingt wie die Art von Sache, die Sie sollten entweder nicht getan werden alle in javascript oder in eine webworker, die gemeint ist, um dieses Problem zu lösen Beschränkung der JS.
InformationsquelleAutor Mike 'Pomax' Kamermans
Wie beschrieben in den "Script zu lange dauert und schweren arbeiten" im Abschnitt Veranstaltungen und timing in die Tiefe (eine interessante Lektüre, übrigens):
Ich bin sicher, es gibt viele Zeiten, in denen eine Aufgabe nicht aufgeteilt in kleinere Aufgaben, oder Fragmente. Aber ich bin sicher, dass es noch viele andere Zeiten, in denen dies möglich ist, auch! 🙂
Einige Umgestaltung ist erforderlich in dem Beispiel. Sie konnte erstellen einer Funktion zu tun, ein Stück von der Arbeit Sie zu tun haben. Konnte es beginnen so:
Sobald die Arbeit beendet ist, sollte die Funktion bestimmen, wenn im nächsten Stück Arbeit erledigt werden muss, oder wenn die Ausführung beendet ist:
Ihre wichtigsten dowork () - Funktion würde wie folgt Aussehen:
Voll funktionierenden code an http://jsfiddle.net/WsmUh/19/ (verhält sich scheinbar sanft auf Firefox).
InformationsquelleAutor German Latorre
Wenn Sie nicht möchten, zu verwenden
setTimeout
dann Sie sind Links mitWebWorker
- dies erfordert HTML5-fähige Browser jedoch.Dies ist eine Möglichkeit, die Sie nutzen können -
Definieren Sie Ihre HTML-und eine inline-Skript (Sie brauchen nicht zu verwenden, inline-Skript, können Sie genauso gut geben, eine url zu einem vorhandenen separaten JS-Datei):
Für das inline-Skript markieren wir es mit dem Typ
javascript/worker
.In der regulären Javascript-Datei -
Die Funktion, die wandelt das inline-Skript in eine Blob-url übergeben werden kann, um einen WebWorker. Beachten Sie, dass dies könnte Hinweis im IE funktioniert, und Sie müssen zum verwenden einer regulären Datei:
Setup Arbeiter:
Empfangen von Nachrichten (oder Befehle) von der
WebWorker
:Treten wir mit einem button-click in dieser demo:
Beispiel hier:
http://jsfiddle.net/AbdiasSoftware/Ls4XJ/
Wie Sie sehen können, das user-interface wird aktualisiert (mit Fortschritt in diesem Beispiel), selbst wenn wir mit einem busy-loop auf die Arbeiter. Getestet wurde dies mit einem Atom-basierten (langsame) computer.
Wenn Sie nicht wollen oder können nicht verwenden Sie
WebWorker
Sie haben VerwendungsetTimeout
.Dies ist, denn dies ist der einzige Weg (neben
setInterval
), mit denen Sie in eine Warteschlange ein Ereignis. Als Sie bemerkt, dass Sie benötigen, um ihm ein paar Millisekunden, da dieses die UI-engine "room to breeth" so-zu-sprechen. JS ist single-threaded, können Sie nicht die Warteschlange von Ereignissen andere Arten (requestAnimationFrame
wird nicht gut funktionieren in diesem Kontext).Hoffe, das hilft.
InformationsquelleAutor
Update: ich glaube nicht, dass in der langen Begriff, dass Sie sicher sein können, dass die Vermeidung von Firefox aggressive Vermeidung von DOM-updates, ohne einen timeout. Wenn Sie erzwingen möchten, dass ein Neuzeichnen /DOM-update, gibt es tricks zur Verfügung, wie die Anpassung der offset des elements, oder tut hide() zeigen(), etc., aber es ist nichts sehr Recht verfügbar, und nach einer Weile, wenn Sie diese tricks misshandelt und verlangsamen user experience, dann Browser aktualisiert werden, zu ignorieren, diese tricks. Lesen Sie diesen Artikel, und die verlinkten Artikel daneben für einige Beispiele: Kraft-DOM neu zeichnen/aktualisieren auf Chrome/Mac
Den anderen Antworten schauen, wie Sie die grundlegenden Elemente, die benötigt werden, aber ich dachte, es wäre sinnvoll zu erwähnen, dass meine Praxis ist, wickeln Sie alle interaktive DOM-ändern-Funktionen in eine "versenden" - Funktion, die Griffe, die notwendigen Pausen benötigt, um rund um die Tatsache, dass Firefox extrem aggressiv in der Vermeidung von DOM-Aktualisierungen, um zu Punkten an den benchmarks (und zu reagieren, um Benutzer beim surfen im internet).
Ich schaute auf Ihre JSFiddle und individualisierter Versand-Funktion ein, dass viele meiner Programme verlassen sich auf. Ich denke, es ist selbsterklärend, und Sie können fügen Sie es in Ihre bestehende JS Fiddle zu sehen, wie es funktioniert:
Hinweis: die dispatching-Funktion auch blockiert Anrufe aus geschieht in der gleichen Zeit, weil es kann ernsthaft die Benutzer verwirren, wenn die status-updates von mehreren Klicks geschehen zusammen.
InformationsquelleAutor Joseph Myers
Versuchen, diese
Ich dachte, das problem war die Verwendung von
innerHTML
das ist, warum ich empfohlen, die Verwendung vonvalue
können Sie bitte teilen Sie Ihre html-button-code?
ja der komplette html-button-code ist : <button id="mybutt" class="buttonEnabled" onclick="longrunningfunction();"><span id="myspan">Ausführung lange Ausführung Funktion</span></button>. auch aktualisiert im ersten post
Warum gibt es eine Spanne in die Taste?
InformationsquelleAutor Jay Patel
Einigen Browsern nicht behandeln
onclick
html-Attribut gut. Es ist besser, verwenden Sie das Ereignis aufjs
Objekt. Wie diese:Machte ich eine Geige mit arbeiten Beispiel http://jsfiddle.net/BZWbH/2/
InformationsquelleAutor Goran Lepur
Haben Sie versucht, indem listener "onmousedown" ändern der button-text und die click-Ereignis für longrunning-Funktion.
InformationsquelleAutor user1390282
Leicht modifiziert Ihren code auf jsfiddle und:
Timeout eingestellt vernünftiger Wert
100ms
hat den trick für mich. Versuchen Sie es.Versuchen Sie die Latenz, die besten zu finden Wert.
InformationsquelleAutor ElmoVanKielmo
DOM-Puffer besteht auch in den Standard-browser auf android,
lange laufende javascript-nur Spülen DOM-Puffer einmal,
verwenden setTimeout(..., 50), um es zu lösen.
InformationsquelleAutor diyism
Fake einen ajax-request
InformationsquelleAutor TeamEASI.com