• Das Erstellen neuer Accounts wurde ausgesetzt. Bei berechtigtem Interesse bitte Kontaktaufnahme über die üblichen Wege. Beste Grüße der Admin

Javascript: Funktion in Objekt übergeben und als Property speichern.

teubs

New member
Guten Tag zusammen,

nachdem ich jetzt leider nach längerem hin und her nicht auf die Lösung des Problems komme frage ich mich nun ob es über diesen Weg überhaupt so machbar ist.
Und zwar möchte ich dem Objekt "animation" über den Parameter "action" eine beliebige Funktion übergeben die es als Property "animation.action" speichert und anschließend dann mit "animation.action()" abgerufen werden kann.
Leider sieht der Debugger die Funktion nicht als Funktion an beim Abrufen von "this.action();".

Code:
var animation = function(action, actionsPerSecond, run){
	this.action = function(){ action(); };
	this.actionsPerSecond = actionsPerSecond;
	this.run = false;
};

animation.prototype.animate = function(){
	setTimeout(function(){
		if(this.run){
			this.action();
			this.animate();
		}
	}, 1000/this.actionsPerSecond);
};

animation.prototype.start = function(){ this.run = true; this.animate(); };
animation.prototype.stop = function(){ this.run = false; };

function renderCurrentFrame(){ ... }

window.onload = function(){
	var framesPerSecond = 60;
	var simulation = new animation(renderCurrentFrame(), framesPerSecond);
	simulation.start();
		
	window.addEventListener("keyup", function(e){
		if(e.keyCode == 32) {
			if(simulation.run == true)	{ simulation.stop(); } 
			else	 				{ simulation.start(); }
		}
	});
}
Bin neu hier im Forum und hoffe auf ne kleine Info zu dem Thema! Konnte leider nichts über jegliche Suchfunktionen finden.
Würd mich riesig freuen, danke im Voraus.

Grüße teubs
 
this.action = action; reicht aus, du benötigst keinen wrapper

setTimeout(function(){
if(this.run){
this.action();
this.animate();
}
}, 1000/this.actionsPerSecond);
die funktion wird im globalen context gerufen, dein this ist dann window

var simulation = new animation(renderCurrentFrame(), framesPerSecond);
renderCurrentFrame() ist ein funktionsaufruf, du willst aber das funktionsobjekt übergeben
 
Perfekt! Da war der Wrapper wohl an falscher Stelle.
Funktioniert jetzt. :)
Dann sag ich mal vielen Dank!
 
this.action = action; reicht aus, du benötigst keinen wrapper
Naja, vielleicht will teubs ja nicht, dass in der Funktion action die animation (@teubs: in JS gibt es die Konvention, dass alle Constructoren mit einem Großbuchstaben beginnen...) Instanz der Context ist...

die funktion wird im globalen context gerufen, dein this ist dann window
Das muss nicht war sein. Wenn der Code in einem strict-Modus ausgeführt wird, wird es einen Fehler in der Fehlerkonsole erzeugen.

@teubs: Du musst eine sogenannte Closure erzeugen, die dir den Zugriff auf deine Instanz erhält:
Code:
animation.prototype.animate = function(){
	var This = this;
	window.setTimeout(function(){
		if (This.run){
			This.action();
			This.animate();
		}
	}, 1000 / this.actionsPerSecond);
};
NB: window.setTimeout() ist bei der Einhaltung der Wartezeit nicht besonders genau. Das kann gerne mal ein paar hundert Millisekunden daneben liegen.


renderCurrentFrame() ist ein funktionsaufruf, du willst aber das funktionsobjekt übergeben
... und das macht man, indem man die Klammern einfach weglässt.
 
in JS gibt es die Konvention, dass alle Constructoren mit einem Großbuchstaben beginnen...
es gibt verscheidene codingstyleguides, das kann in einem so definiert sein, aber "in JS" gibt es diese konvention nicht, sonst wäre es teil der syntax
ich sollte mir für solche ständig wiederkehrenden diskussionen ne linkliste anlegen
 
Zuletzt bearbeitet:
Eine Konvention ist niemals Teil der Syntax. Deswegen heißt es ja auch Konvention... in C gibt es z.B. auch die Konvention, alle Makros in Großbuchstaben zu schreiben. Muss man sich nicht dran halten, erleichter aber fremden Codelesern das Verständniss ungemein.

Dass es eine Konvention gibt (und diese gibt es auf jeden Fall: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml#Naming ) heißt noch lange nicht, dass nicht auch eine andere gibt...

Und alle Konsturktoren in ECMA haben einen Großbuchstaben am Anfang und die "normalen" Funktion nicht... wenn du also gerne eine Konvention verwenden willst, die nicht konsistent mit dem Sprachkern ist, ist das deine Sache, aber einen Neuling weise ich immer darauf hin. Ob er/sie sich dann daran hält, ist seine/ihre Sache.
 
in C gibt es z.B. auch die Konvention, alle Makros in Großbuchstaben zu schreiben.
nein, die gibt es nicht in c, es gibt viele, die man auch in verschiedenen sprachen nutzen kann. es gibt z.b. die ungarische notation, die ms verwendet.

Dass es eine Konvention gibt (und diese gibt es auf jeden Fall: https://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml#Naming ) heißt noch lange nicht, dass nicht auch eine andere gibt...

genau.


Muss man sich nicht dran halten, erleichter aber fremden Codelesern das Verständniss ungemein.
ja, dagegen sagt ja keiner wass
würdest du schreiben, "die meisten schreiben konstruktoren mit einem großbuchstaben am anfang, das finde ich sinnvoll um diese von normalen variablen zu unterscheiden" würde ich ja auch nichts sagen.
aber warum das gerade immer bei dieser einen regel anbringen, warum nicht bei einrückungen (meist als 2 leerzeichen definiert)?
 
Vielen Dank euch.
Werde die Konvention wohl mit übernehmen, allein der Übersicht halber. Ob muss oder nicht ist da jetzt mal egal.
 
NB: window.setTimeout() ist bei der Einhaltung der Wartezeit nicht besonders genau. Das kann gerne mal ein paar hundert Millisekunden daneben liegen.

Das ist mir bereits bekannt. Wenn wir schon dabei sind: Gibt es denn für diesen Fall eine genauere Alternative? setIntervall ist ja ähnlich ungenau nehme ich an?
 
nein, die gibt es nicht in c, es gibt viele
Anscheinend weiß du nicht, was "es gibt" heißt...
Hast du die schon mal in irgendeinem JS-Projekt gesehen? Und wirklich gut lesbar wird der Code dadurch auch nicht. Super finde ich ja den Bezeichner "ich"...

ja, dagegen sagt ja keiner wass
Warum regst du dich dann auf?
"die meisten schreiben konstruktoren mit einem großbuchstaben am anfang
genau das ist eine Konvention... und hier ist es sogar die Konvention, an die sich die Meisten halten.
aber warum das gerade immer bei dieser einen regel anbringen
Warum nicht?
, warum nicht bei einrückungen
Äh... ich spreche es meistens an, wenn ein Neuling keinerlei Einrückung macht.
(meist als 2 leerzeichen definiert)?
Ich würde nicht darauf wetten, dass die Meisten zwei Leerzeichen als Einrückung verwenden (anscheinend verwenden ~3/4 Leerzeichen (Quelle: http://evadeflow.com/2011/03/tabs-vs-spaces-in-the-21st-century/ ), aber die Anzahl variiiert zwischen 2 und 8.
Auch ist das ziemlich egal, da es nur um die Strukturierung beim Einrücken geht. Um wieviel und mit welchem Zeichen ist dabei ziemlich wurst. Lesbar ist lesbar.

Vielen Dank euch.
Werde die Konvention wohl mit übernehmen, allein der Übersicht halber.
Bitte - gern geschehen. Wenn du noch etwas weiter gehen willst, kannst du deinen Code auch noch durch jslint oder http://www.jshint.com/ jagen und da alles ausmerzen.

Das ist mir bereits bekannt. Wenn wir schon dabei sind: Gibt es denn für diesen Fall eine genauere Alternative? setIntervall ist ja ähnlich ungenau nehme ich an?
window.setTimeout() und window.setInterval() sind ähnlich. Etwas besser ist window.requestAnimationFrame() , aber auch nicht perfekt. Für Animationen misst man am Besten die Zeit zwischen zwei "Ticks" (über ein Date-Objekt) und lässt die Animation dann so weit fortschreiten, dass es eine konstante Animationsgeschwindigkeit ergibt.
 
Anscheinend weiß du nicht, was "es gibt" heißt...
dann kläre mich auf

Hast du die schon mal in irgendeinem JS-Projekt gesehen? Und wirklich gut lesbar wird der Code dadurch auch nicht. Super finde ich ja den Bezeichner "ich"...
du hast von c angefangen, und ja, da habe ich sie gesehen und benutzt, und es wird sogar lesbarer

Warum regst du dich dann auf?
mach ich das? ich weise nur darauf hin, dass es nicht DEN styling guide gibt, sondern mehrere, bzw. jeder seine eigenen stil haben darf

was macht diese so besonders?


nein, im gegenteil, erkennbar schon daran, dass du dort keine zeit vorgeben kannst
requestAnimationFrame ist nur performanter, bzw. reiht sich die berechnung besser in den renderingprozess ein
 
dann kläre mich auf
Ich verwende "es gibt" äquivalent zu "es existiert". Ist eine reine Existenzaussage und schließt nichts anderes aus. Wenn du "gibt es nicht" schreibst, verneinst du die Existenz, was ja falsch ist, da sie schon existiert...

du hast von c angefangen
war ja nur ein Beispiel...
, und ja, da habe ich sie gesehen und benutzt
Danach hab' ich nicht gefragt, sondern nach JS.
, und es wird sogar lesbarer
Hm... darüber kann man streiten - wenn man das gewohn ist, stimm' ich dir zu, aber das ist bei jeder Namenskonvention der Fall. Ich bin ein Freund von langen, sprechenden Variablennamen, da das prinizipiell Tippen beim Programmieren nicht der zeitlimitierende Teil sein sollte, sondern das Überlegen und Testen. Da ist die Lernkurve für die Namenskonvention viel kürzer und wenn man sich mal nicht 100%ig an eine Einschränkung/Erweiterung (z.B. bei Funktionen Verb vor Nomen) hält, ist es nicht so schlimm. Und Außenstehende, die noch nie etwas von der Namenskonvention gehört haben, verstehen den Code sofort.

Kam bei mir so an.
ich weise nur darauf hin, dass es nicht DEN styling guide gibt
Das hab' ich nie gesagt.
, sondern mehrere, bzw. jeder seine eigenen stil haben darf
Auch das hab' ich nie abgestritten.

was macht diese so besonders?
Äh... ist die, die teubs nicht verwendet hat. Deswegen hab' ich sie angesprochen... warum sollte ich eine Konvention ansprechen, an die er sich sowieso schon hält (z.B. camelCase)?


nein, im gegenteil, erkennbar schon daran, dass du dort keine zeit vorgeben kannst
Warum soll das ein Nachteil sein? Das Konzept ist hald anders.
Die Aufrufefrequenz ist konstanter/verlässlicher und deswegen ist es auch besser für Animationen geeignet (wie schon der Name andeuted).
 
Danach hab' ich nicht gefragt, sondern nach JS.
dann versteh ich den sinn der frage nicht.
die ungarische notation in einer dynamisch typisierten sprache ist wenn überhaupt nur eingeschränkt sinnvoll.
in statisch typisierten sprachen wie c++, hilft es aber, anhand des namens der variablen auf den typ schliessen zu können.

Das hab' ich nie gesagt.
Auch das hab' ich nie abgestritten.
So wie du es Ausdrückst schon.
Konvention
Eine Konvention (Aussprache: [k?nv?n'?i?o?n]; vom lateinischen conventio für „Übereinkunft“ oder „Zusammenkunft“) ist eine nicht formal festgeschriebene Regel, die von einer Gruppe von Menschen aufgrund eines Konsenses eingehalten wird.
in JS gibt es die Konvention, dass alle Constructoren mit einem Großbuchstaben beginnen
die regel: "alle Constructoren mit einem Großbuchstaben beginnen"
die gruppe: "in JS" => alle die JS nutzen => DAS ist falsch

warum sollte ich eine Konvention ansprechen, an die er sich sowieso schon hält (z.B. camelCase)?
ahh, sehr gutes beispiel, das ist eine regel auf gleichem niveau wie die obige.
hast du die schon mal angemeckert? (musst kein link raussuchen, wenn du sagst ja, reicht mir das)

du meckert 3 sachen immer wieder an und stellst sie dar, als wären sie gesetz:
1) die mit dem konstruktor
die ist mMn nicht mal erwähnenswert, keine ahnung warum sie bei dir einen so hohen stellenwert hat(der schlaue hat auch immer darauf hingewiesen)
wie gesagt, bei einem "die meisten schreiben konstruktoren mit einem großbuchstaben am anfang, das finde ich sinnvoll weil..." würde ich mich zwar fragen warum, aber sonst nichts sagen
2) die mit den ===
die ist aus den "good parts", die sind aber n einer zeit entstanden, als plötzlich jeder dau, der vorher in visual basic sharewareprogramme geschrieben hat die m in mm umrechnen, angefangen hat js zu schreiben. und für diese daus sind diese regeln gemacht. und das halte ich für falsch. automatische typecasts sind ein wichtiges feature, selbst in typisierten sprachen wie c++. in js gibt es ein paar ungewöhnliche/unerwartete casts, diese aufzuzeigen und zu erklären ist sinnvoll, deswegen darauf zu verzichten nicht.
3) die mit den {}-klammern
auch aus den "good parts", selbe zielgruppe, aber anstelle dieser zu zeigen, daß curly braces unterschiedliche bedeutung haben und an einer stelle probleme machen können, wird einfach die regel eingeführt curly braces immer auf dieselbe zeile zu schreiben wie das vorherige statement.


Warum soll das ein Nachteil sein?
ich habe nicht gesagt, dass es ein Nachteil ist, sondern, dass es unmöglich ist eine gewählte zeit einzuhalten, wenn man diese nicht mal vorgeben kann.

Die Aufrufefrequenz ist konstanter/verlässlicher und deswegen ist es auch besser für Animationen geeignet (wie schon der Name andeuted).
besser für Animationen geeignet, ja. aber die Aufrufefrequenz ist nicht konstanter, im gegenteil. sie ist für Animationen optimiert. diese lösen ein rendern der seite auf. deswegen wird das callback unter anderem vor dem rendern der seite gerufen und damit 2 fliegen mit einer klappe erschlagen
 
dann versteh ich den sinn der frage nicht.
die ungarische notation in einer dynamisch typisierten sprache ist wenn überhaupt nur eingeschränkt sinnvoll.
Ich hatte das:
es gibt viele, die man auch in verschiedenen sprachen nutzen kann. es gibt z.b. die ungarische notation, die ms verwendet.
in Bezug auf JS gelesen... deswegen erschien es mir auch nicht wirklich sinnvoll.

in statisch typisierten sprachen wie c++, hilft es aber, anhand des namens der variablen auf den typ schliessen zu können.
Wenn man seinen Variablen gescheite Namen gibt, braucht man solche Hilfskonstrukte nicht unbedingt... aber sie können helfen. Aber sie haben hald eine sehr hohe Einstiegsschwelle.

So wie du es Ausdrückst schon.
Konvention


die regel: "alle Constructoren mit einem Großbuchstaben beginnen"
die gruppe: "in JS" => alle die JS nutzen => DAS ist falsch
Der erste Folgepfeil ist, meiner Meinung nach, falsch. Jedenfalls war das nicht so gemeint. "in JS" bedeutet für mich mehr
Also mir ist noch nie eine Programmierkonvention begegnet, an die sich alle halten...

ahh, sehr gutes beispiel, das ist eine regel auf gleichem niveau wie die obige.
hast du die schon mal angemeckert? (musst kein link raussuchen, wenn du sagst ja, reicht mir das)
Puh - keine Ahnung. Kann sein. Kann mich jetzt an keinen Fall erinnern.
Meistens sieht man ja sowas im PHP-Forum und PHP ist ja selbst im Sprachkern extrem inkonsistent.

Aber ich finde nicht, dass das das gleiche Niveau ist. Ob jetzt eine Funktion "linkItem" oder "LinkItem" heißt, macht einen großen Unterschied, wenn man sich an die Konvention hält. Das eine ist eine Funktion, die irgendwas verlinkt, und die andere ist ein Konstruktor eines LinkItem-Objektes. Hingegen ist "generate_link" und "generateLink" ziemlich äquivalent (und "generatelink" ist einfach nur schwer zu lesen).

du meckert 3 sachen immer wieder an und stellst sie dar, als wären sie gesetz:
Äh... nein... wenn ich es als Gesetzt darstellen würde, würde ich "man muss" und "man darf nicht" schreiben. Da es keine Gesetzte sind, schreibe ich das nicht. Wenn das bei dir so ankommt, tut mir das leid. Werde versuchen, mich da klarer auszudrücken.

1) die mit dem konstruktor
die ist mMn nicht mal erwähnenswert, keine ahnung warum sie bei dir einen so hohen stellenwert hat(der schlaue hat auch immer darauf hingewiesen)
wie gesagt, bei einem "die meisten schreiben konstruktoren mit einem großbuchstaben am anfang, das finde ich sinnvoll weil..." würde ich mich zwar fragen warum, aber sonst nichts sagen
Ich habe oben "es gibt die Konvention" geschrieben. Es geht dabei um die Lesbarkeit des Codes. Wenn man sich an die Standardkonvention (also die, die auch im Sprachkern eingehalten wird) hält, hat es der Leser des Codes (und damit meine ich auch den Schreiber des Codes selbst, wenn er in ein paar Wochen auf den Code schaut) viel leichter den Code zu verstehen, da man sofort sieht, was ein Konstruktor und was eine "normale" Funktion ist.

Falls du es noch nicht weißt: Ich bin faul! Deswegen nehme ich manchmal etwas mehr Arbeit auf mich, um in der Zukunft viel weniger Arbeit zu haben. Gescheiter Codestil und konsistente Namensgebung (konsistent auch mit dem Sprachkern) gehören für mich da dazu.
Netter Vortrag allgemein zum Thema: The Lazy Programmer's Guide to Secure Computing - YouTube
2) die mit den ===
die ist aus den "good parts", die sind aber n einer zeit entstanden, als plötzlich jeder dau, der vorher in visual basic sharewareprogramme geschrieben hat die m in mm umrechnen, angefangen hat js zu schreiben. und für diese daus sind diese regeln gemacht. und das halte ich für falsch. automatische typecasts sind ein wichtiges feature, selbst in typisierten sprachen wie c++. in js gibt es ein paar ungewöhnliche/unerwartete casts, diese aufzuzeigen und zu erklären ist sinnvoll, deswegen darauf zu verzichten nicht.
OK - zeige mir ein wirklich sinnvolles Beispiel, das nur mit "==" und nicht mit "===" funktioniert.
Ich will die Fragesteller hier jetzt nicht als DAUs bezeichnen, aber oft sind es Anfänger. Deswegen kennen sie die seltsamen Casts von JS nicht.

3) die mit den {}-klammern
auch aus den "good parts", selbe zielgruppe, aber anstelle dieser zu zeigen, daß curly braces unterschiedliche bedeutung haben und an einer stelle probleme machen können, wird einfach die regel eingeführt curly braces immer auf dieselbe zeile zu schreiben wie das vorherige statement.
OK - anscheinend bist du nicht faul und willst dir anstelle von einer Regel ohne Ausnahme eine mit Ausname merken. Auch sieht der Code dann auch nicht mehr ganz konsistent aus. Wenn du das trotzdem verwenden willst, ist das deine Entscheidung.

Ansonsten ist der Einrückungsstil ja meistens wirklich Geschmackssache - solange man konsistent ist.

Du hast document.write() vergessen. ;)

ich habe nicht gesagt, dass es ein Nachteil ist, sondern, dass es unmöglich ist eine gewählte zeit einzuhalten, wenn man diese nicht mal vorgeben kann.
OK - dann hatte ich dich falsch verstanden.

aber die Aufrufefrequenz ist nicht konstanter, im gegenteil.
Bitte belege das. Bei meinen Versuchen hatte ich recht konstant 50 Hz - was ja auch sein muss, da mein Monitor mit 50 Hz läuft.
sie ist für Animationen optimiert.
Ja und? Warum sollte dann die Aufrufefrequenz weniger stabil sein? Animationen sind an einen Bildschirm gekoppelt, der mit einer festen Frequenz arbeitet.
 
Du hast document.write() vergessen. ;)
mist
der grüne ist wohl weg?

Bitte belege das. Bei meinen Versuchen hatte ich recht konstant 50 Hz
und browserunterschiede?

Ja und? Warum sollte dann die Aufrufefrequenz weniger stabil sein?
weil ich den browser z.b. durch js zum rendern veranlassen kann. wann gerendert wird ist nicht vorhersehbar.

Animationen sind an einen Bildschirm gekoppelt, der mit einer festen Frequenz arbeitet.
animationen sind ans rendern gekoppelt, und das passiert, wenn sich was am dom ändert.
 
der grüne ist wohl weg?
:D - anscheinend... @mo: kannst du den wieder reinbringen?

und browserunterschiede?
Hier mein kleiner Test:
Code:
<!DOCTYPE html>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Fenstertitel</title>
<script type="text/javascript" src="//kkjs.kkapsner.de/modules/kkjs.load.js?modules=Timer"></script>
<style type="text/css"></style>
</head>
<body>Running...
<script type="text/javascript">
var t = new kkjs.Timer(10000);
t.animation = true;
var lastNow = Date.now();
var sum = 0;
var count = 0;
var sum2 = 0;
t.on("tick", function(){
	var now = Date.now();
	var diff = now - lastNow;
	sum += diff;
	count += 1;
	sum2 += diff * diff
	lastNow = now;
});
t.start();

t.on("timeOver", function(){
	t.stop();
	document.body.innerHTML = kkjs.sprintf(
		"mean: %f ± %f",
		sum / count,
		Math.sqrt(sum2/count - sum*sum/count/count)
	);
});
</script>
</body>
</html>

und meine Ergebnisse (Rechner dabei komplett ohne Last - auch keine Mausbewegungen):
Firefox 29: mean: 20 ± 0.8717797887081294
Chrome 34: mean: 19.92430278884462 ± 1.0070701320903352
Opera 20: mean: 19.882703777335983 ± 1.362724089484473
IE 11: mean: 20.008 ± 1.4085226302761242
Safari kann ich nicht testen.
Ich finde das recht gut. Wenn man den Rechner jetzt belastet oder in der Callbackfunktion jetzt was Rechenintensives macht kann die Stabilität natürlich leiden.

weil ich den browser z.b. durch js zum rendern veranlassen kann. wann gerendert wird ist nicht vorhersehbar.
Ja aber darum geht es bei window.requestAnimationFrame() doch auch gar nicht. Das ruft die Funktion ja nicht dann auf, wenn irgendwas anderes ein Rendern der Seite nötig macht - das könnte ja theoretisch ewig dauern. Sondern es sagt: ruf meine Funktion vor dem nächsten möglichen Rendern auf. So hab' ich das jedenfalls verstanden und meine Tests zeigen das auch.

animationen sind ans rendern gekoppelt, und das passiert, wenn sich was am dom ändert.
...und das Rendern an den Monitor. Und Rendern passiert nicht immer, wenn sich was im DOM ändert und kann auch bei anderen Sachen (z.B. Scrollen) ausgelöst werden. Aber, wie schon gesagt, sollte das irrelevant sein, da es nur um den möglichen Renderzeitpunkt geht.
 
Ja aber darum geht es bei window.requestAnimationFrame() doch auch gar nicht.
was heisst, darum geht es nicht? nein, bzw. doch.
requestAnimationFrame ist die antwort auf das problem.
angenommen du hast viele animationen.
animation 1 berechnet etwas im callback und ändert was im dom => der browser muss rendern.
dann kommt animation 2 bis n => es wird n fach gerendert.
requestAnimationFrame sorgt jetzt dafür, das alle animationen vor einem sowieso benötigten rendern gerufen werden, dort ihre berechnungen machen und das dom ändern können. => nur noch einmal rendern, wenn sowieso gerendert werden muss

Das ruft die Funktion ja nicht dann auf, wenn irgendwas anderes ein Rendern der Seite nötig macht
warum nicht? das ist doch die ideale stelle

das könnte ja theoretisch ewig dauern.
natürlich kann das sein, war nach einer gewissen zeit kein rendern nötig, wird ein aufruf der animationen zwischengeschoben

Sondern es sagt: ruf meine Funktion vor dem nächsten möglichen Rendern auf.
ja, das sage ich doch auch? und das ist doch genau das was das ganze unvorhersehbar macht. an irgendeiner stelle wird irgendwann irgendwas ins dom eingefügt. rendern erforderlich! callbacks werden gerufen.

...und das Rendern an den Monitor.
was hat das rendern mit dem monitor zu tun? klar, man kann die zusätzlich nötigen zwischenaufrufe, wnn kein rendern nötig war, an bekannte parameter anpassen(das auge nimmt max. x bilder pro sek. war, darum ist eine framerate von y gut), aber der browser rendert nur, wenn er muss, wen es änderungen gibt.

Und Rendern passiert nicht immer, wenn sich was im DOM ändert
das wäre in bug

und kann auch bei anderen Sachen (z.B. Scrollen) ausgelöst werden.
ja auch dann muss gerendert werden

Aber, wie schon gesagt, sollte das irrelevant sein, da es nur um den möglichen Renderzeitpunkt geht.
den beeinflusst du doch aber damit. du scrollst => rendern nötig => callback rufen
 
was heisst, darum geht es nicht? nein, bzw. doch.
Wenn ich eine Animation mache, will ich nicht darauf warten, dass irgendwas Anderes ein Rendern nötigt macht...
requestAnimationFrame ist die antwort auf das problem.
[...]
Mit ist das Problem und die Lösung schon klar.

warum nicht? das ist doch die ideale stelle
Nein, ist es nicht. Die ideale Stelle ist vor dem nächsten möglichen Renderzeitpunkt.

natürlich kann das sein, war nach einer gewissen zeit kein rendern nötig, wird ein aufruf der animationen zwischengeschoben
Da sagen meine Tests was anderes. Da wurde requestAnimationFrame kontinuierlich alle 20ms (= 50Hz = Frequenz des Monitors) aufgerufen obwohl überhaupt gar nichts irgendwie auf dem Bildschirm gerendert werden musste in den 10 Sekunden. Wie gesagt, ich hab' noch nicht einmal die Maus bewegt.


ja, das sage ich doch auch? und das ist doch genau das was das ganze unvorhersehbar macht. an irgendeiner stelle wird irgendwann irgendwas ins dom eingefügt. rendern erforderlich! callbacks werden gerufen.
Nein, das sagst du nicht. Du sagst "beim nächsten nötigen Rendern" und ich sage "beim nächsten möglichen Renderzeitpunkt". Das macht einen riesen Unterschied: deines ist nicht vorherseh bar und meines schon (in gewissen Grenzen). Wenn du Tests hast, die deine Meinung belegen, sehe ich sie mir gerne an. Den Test, der meine Meinung bestätig (so jedenfalls interpretiere ich das), hab' ich dir ja schon gezeigt.

Wenn ich dich falsch verstehe, sag's bitte.

was hat das rendern mit dem monitor zu tun?
Äh... ohne Monitor brauchst du gar kein Rendern, da man nichts sieht...
klar, man kann die zusätzlich nötigen zwischenaufrufe, wnn kein rendern nötig war, an bekannte parameter anpassen(das auge nimmt max. x bilder pro sek. war, darum ist eine framerate von y gut), aber der browser rendert nur, wenn er muss, wen es änderungen gibt.
Natürlich rendert der nur, wenn er muss. Aber requestAnimationFrame stößt ja auch kein Rendern direkt an. Nur was darin passiert, kann ein Rendern anstoßen.

Nö, wäre es nicht. Wenn ich im DOM ein verstecktest Element verändere muss nicht gerendert werden.


den beeinflusst du doch aber damit. du scrollst => rendern nötig => callback rufen
... ich kann mich nur wiederholen... der Callback wird aufgerufen, auch wenn kein Rendern nötig ist...

Technisches Zitat, auf das ich zusätzlich meine Meinung aufbaue:
https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame schrieb:
This will request that your animation function be called before the browser performs the next repaint. The number of callbacks is usually 60 times per second, but will generally match the display refresh rate in most web browsers as per W3C recommendation. The callback rate may be reduced to a lower rate when running in background tabs.
 
Wenn ich eine Animation mache, will ich nicht darauf warten, dass irgendwas Anderes ein Rendern nötigt macht...
Nein, aber wenn schon gerendert werden muss, kann man hier prima einen aufruf machen.

Nein, ist es nicht. Die ideale Stelle ist vor dem nächsten möglichen Renderzeitpunkt.
einen möglichen renderzeitpunkt kennt der browser aber nach dem parsen nicht mehr.

Da sagen meine Tests was anderes. Da wurde requestAnimationFrame kontinuierlich alle 20ms (= 50Hz = Frequenz des Monitors) aufgerufen obwohl überhaupt gar nichts irgendwie auf dem Bildschirm gerendert werden musste in den 10 Sekunden. Wie gesagt, ich hab' noch nicht einmal die Maus bewegt.
ja, nochmal, das ist ja logisch, wenn nichts gerendert werden muss, muss er aufrufe zwischenschieben.


Nein, das sagst du nicht. Du sagst "beim nächsten nötigen Rendern" und ich sage "beim nächsten möglichen Renderzeitpunkt". Das macht einen riesen Unterschied:
wie soll der browser wissen, wann du einen button drückst, an dem ein clickhander hängt der das dom ändert?

deines ist nicht vorherseh bar und meines schon (in gewissen Grenzen).
nein, deines ist genausowenig vorhersehbar, nichtmal für den browser

Wenn du Tests hast, die deine Meinung belegen, sehe ich sie mir gerne an. Den Test, der meine Meinung bestätig (so jedenfalls interpretiere ich das), hab' ich dir ja schon gezeigt.
dein test war ja, wie du selbst sagst, ohne jegliches rendern, sogar ohne belastung.

Wenn ich dich falsch verstehe, sag's bitte.
ja, irgendwie glaube ich auch, daß wir aneinander vorbei reden

Äh... ohne Monitor brauchst du gar kein Rendern, da man nichts sieht...
das ist dem browser aber egal, der weiss nicht ob du den Monitor an oder aus hast oder nicht angeschlossen. der malt sein bild bei jeder änderung in sein devicecontext und gut.

Natürlich rendert der nur, wenn er muss. Aber requestAnimationFrame stößt ja auch kein Rendern direkt an. Nur was darin passiert, kann ein Rendern anstoßen.
ja, sagte ich was anderes? bis auf das "nur" in dem satz bin ich bei dir.

Nö, wäre es nicht. Wenn ich im DOM ein verstecktest Element verändere muss nicht gerendert werden.
ok

... ich kann mich nur wiederholen... der Callback wird aufgerufen, auch wenn kein Rendern nötig ist...
nochmal, ja, dagegen sage ich ja gar nichts. ich sage aber, durch änderungen an sichtbaren dom-elementen, die keiner vorhersehen kann wird es auch aufgerufen. und diese sind unvorhersehbar.

Technisches Zitat, auf das ich zusätzlich meine Meinung aufbaue:
requestAnimationFrame method (Internet Explorer)
Registers a function to call when the system is ready to update (repaint) the display.
https://developer.mozilla.org/en-US/docs/Web/API/window.requestAnimationFrame
This will request that your animation function be called before the browser performs the next repaint.
 
Nein, aber wenn schon gerendert werden muss, kann man hier prima einen aufruf machen.
Natürlich. Das bestreite ich auch nicht.


einen möglichen renderzeitpunkt kennt der browser aber nach dem parsen nicht mehr.
Sollte er aber (ich kenne jetzt die Browserimplementation nicht so gut, dass ich sagen könnte, dass jeder Browser das kann). Vor jedem neuen Bildschirmbildaufbau ist ein guter Renderzeitpunkt.

ja, nochmal, das ist ja logisch, wenn nichts gerendert werden muss, muss er aufrufe zwischenschieben.
Habe einen kleinen Test gemacht:
Code:
<!DOCTYPE html>

<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=UTF-8">
<title>Fenstertitel</title>
<script type="text/javascript" src="//kkjs.kkapsner.de/modules/kkjs.load.js?modules=Timer,sprintf"></script>
</head>
<body>
	Running...
	<div id="timer"></div>
	<div id="animationResult"></div>
	<div id="normalResult"></div>
<script type="text/javascript">
function generateTimer(output){
	var t = new kkjs.Timer(10000);
	var lastNow = Date.now();
	var sum = 0;
	var count = 0;
	var sum2 = 0;
	t.on("tick", function(){
		var now = Date.now();
		var diff = now - lastNow;
		sum += diff;
		count += 1;
		sum2 += diff * diff
		lastNow = now;
	});

	t.on("timeOver", function(){
		t.stop();
		output.innerHTML = kkjs.sprintf(
			"mean: %f ± %f",
			sum / count,
			Math.sqrt(sum2/count - sum*sum/count/count)
		);
	});
	return t;
}

var t = generateTimer(kkjs.$("animationResult"));
t.animation = true;

var t2 = generateTimer(kkjs.$("normalResult"));
t2.tickTime = 0;
t2.on("tick", function(){
	kkjs.$("timer").innerHTML = this.getTimeString() + " (" + Math.random() + ")";
});

t2.start();
t.start();
</script>
</body>
</html>
- hier wird so schnell wie möglich (window.setTimeout(fnc, 0)) ein neues Rendern nötig.
Ergebnis:
Code:
Chrome:
	animation: mean: 19.922310756972113 ± 1.395760598544772
	setTimeout: mean: 4.93339911198816 ± 0.5161472008683037
Firefox:
	animation: mean: 20.044088176352705 ± 2.0263940055111886
	setTimeout: mean: 4.156691604322527 ± 2.249589162193331
IE:
	animation: mean: 20.014 ± 1.240082255336312
	setTimeout: mean: 3.360551075268817 ± 1.4161283800521635
Opera:
	animation: mean: 19.882703777335983 ± 1.3227475493268288
	mean: 4.995504495504496 ± 0.1563819520112744
kein großartiger Unterschied zum alten Test... (ich sehe einen Unterschied, wenn der Tab den Fokus nicht hat, aber es steht ja auch überall, dass dann die Frequenz reduziert ist. Auch wenn man wie wild rumscrollt, wird's langsamer im FF und IE).

Auch sieht man, dass zwar ca. alle 4ms eigentlich ein neues Rendern nötig ist (der Zufallstext hat sich geändert) aber trotzdem nur alle 20ms der Repaint ausgeführt wird...


wie soll der browser wissen, wann du einen button drückst, an dem ein clickhander hängt der das dom ändert?
Was hat den das damit zu tun? Wie man im Test oben sieht, markiert der Browser dann nur "Rendern nötig" und macht das dann vor dem nächsten Renderzeitpunkt.


nein, deines ist genausowenig vorhersehbar, nichtmal für den browser
Wenn mein Monitor 50 Hz hat, hab' ich alle 20 ms einen idealen Renderzeitpunkt... das kann man wunderbar vorhersehen... also ich kann das.


dein test war ja, wie du selbst sagst, ohne jegliches rendern, sogar ohne belastung.
Oben neuer Test. Zwar immer noch ohne Belastung, aber Belastung macht JS prinzipiell langsam, da es mit einer sehr geringen Priorität läuft.


ja, irgendwie glaube ich auch, daß wir aneinander vorbei reden
Das kann gut sein - ich kann's nur nicht genau ausmachen, wo genau unser Kommunikationsproblem liegt...


das ist dem browser aber egal, der weiss nicht ob du den Monitor an oder aus hast oder nicht angeschlossen. der malt sein bild bei jeder änderung in sein devicecontext und gut.
Natürlich weiß der, welchen Monitor ich habe. Das komplette screen-Objekt wäre dann nicht realisierbar. Auch wären die ganzen Hardwarebeschleunigungssachen dann nicht möglich.


ja, sagte ich was anderes?
Gut - dann sind wir uns ja in dem Punkt einig.
bis auf das "nur" in dem satz bin ich bei dir.
Das "nur" ist doppeldeutig. Ich meinte nicht "nichts außer" sondern eher... ach streich' das "nur" einfach komplett aus dem Satz... und auch gleich noch das Komma; das ist falsch.

nochmal, ja, dagegen sage ich ja gar nichts. ich sage aber, durch änderungen an sichtbaren dom-elementen, die keiner vorhersehen kann wird es auch aufgerufen. und diese sind unvorhersehbar.
Der Test oben zeigt etwas anderes. Aber jetzt verstehe ich allmählich, was dein Punkt ist.


Das "ready to update" interpretiere ich als "möglicher Renderzeitpunkt". Und wenn ich eine Renderengine schreiben würde, würde ich dann einen Repaint durchführen, wenn das für das Augabegerät optimal ist. Also alle 20ms bei einem 50Hz Monitor. Alles, was da dazwischen, würde ich immer zusammenfassen. Und so wie die Tests aussehen, scheint das bei den vieren auch der Fall zu sein - so interpretiere ich jedenfalls die Ergebnisse.
 
Zurück
Oben