Hallo Community,
ich möchte Variablen aus einer JSON-Datei sekündlich laden.
Dazu hab ich ein kleines Script geschrieben:
JSON-Datei:
1
{
2
"temp_1": 10,
3
"pumpe_1": 1
4
}
JavaScript-Datei:
1
/** URL zur Variablendefinierung - JSON-Format */
2
var urlVariables = "./variables/variables.html";
3
function nameVariables(jd){
4
/** Variablen deklarieren */
5
temp_1 = (jd.temp_1);
6
pumpe_1 = (jd.pumpe_1);
7
}
8
function updateVariables(){
9
$.getJSON(urlVariables, nameVariables);
10
}
11
/** Alle 1000ms werden die Variablen aktualisiert */
12
updateVariables();
13
setInterval(updateVariables, 1000);
Die Variablen sollen dann Global verfügbar sein, weil Anzeigen,
Graphen,... davon abhängig sind und dynamisch aktualisiert werden.
Das Script funktioniert, wenn ich nur eine Variable verwende wie z.B.
temp_1.
Aber eine 2te oder mehr Variablen funktionier nicht.
Ich suche jetzt schon ein paar Stunden an dem Fehler, aber ich komme
nicht darauf.
Kann mir da vll. jemand einen Tipp geben/helfen?
Danke und Mfg,
Tropaion
Ich habe ein 2te Script wo ich die Variable so verwende, was aber nicht
funktioniert. Kann es daran liegen das die Variable nicht übergeben
wird?
Weil wenn ich sie im selben Script vor der Funktion defniere
funktioniert es.
Fabian P. schrieb:> Ich habe ein 2te Script wo ich die Variable so verwende, was aber nicht> funktioniert.
Und in deinem 2. Script kommt weder "temp_1" noch "pumpe_1" vor. Kann
sein, dass es sich hier um ein Verständnisproblem meinerseits handelt.
Aber das könnte man ganz einfach umgehen indem du einfach deinen
gesamten Code posten würdest und auch erwähnen würdest, wie du den
ausführst. JScript, Firefox, NodeJS, Rhino,...?
Firefox-Fehlermeldungen schon gelesen? Das kann manchmal durchaus
hilfreich sein (ironisch gemeint; es ist fast immer sinnvoll).
> ReferenceError: pump_1 is not defined" in "functions.js" (Zeile 3).
Das sollte wohl "pumpe_1" heißen, oder?
du hat da nen type, an manchen stellen nutzt du pump_1 an anderen
pumpe_1.
in der Heizkreis2.html klappt das dann. in der heizkessel1.html nicht,
da fehlt glaub ich der Aufruf zur functions.js.
Du solltest dein json file auch .json nennen, je nach einstellung mag
dein browser es nicht wenn json mit falschem content-type ausgeliefert
wird.
Ich habe es bist jetzt immer nur mit Heizkreis 1 probiert.
Die anderen Seiten sind filler.
Ob es mit dem Format JSON geht muss ich schauen, ich weis nemlich nicht
ob die SPS auf der ich das Lade kann.
Bin die Variablen jetzt noch mal in Ruhe durchgegangen und ich bin der
Meinung es sollte passen. .json hab ich jetzt auch reingetan.
Die Temperaturanzeige funktioniert auch (dynamisch).
Habe das script functions ganz unten eingebunden, weil es ja erst laden
soll wenn das DOM-Model vollständig ist sonst kann es ja nicht
funktionieren.
Nach rumprobiern bin ich der Meinung das die Variable das script nicht
"erreicht". Denn beide funktionen selbst funktionieren ja.
Im Anhang geänderte Dateien.
Ich muss mich entschuldigen wenn der Code nicht besonders schön ist, ich
arbeite erst seit ein paar Tagen intensiv mit JS.
> weil es ja erst laden soll wenn das DOM-Model vollständig ist
Dafür hat das Fenster das Event "onload".
Und dafür, daß das nach geldverdienen klingt, seid ihr sehr unbeleckt.
Also erstens mal bin ich berufsuntätig, ich bin Schüler an einer
technischen Schule.
Dieses Projekt mache ich in meiner Freizeit um mein Wissen und Können zu
erweitern. Es wird wahrscheinlich nie verwendet werden geschweige denn
verkauft. Höchstens auf meiner Webseite als OpenSource-Projekt
veröffentlicht. (OpenSource-Befürworter ;) )
Wenn es Geld verdienen wäre wäre es nicht verkaufbar da stimme ich dir
zu.
Aber was erwartet man von jemanden der seit 4 Tagen mit JavaScript
arbeitet ;)
Von "onload" hab ich schon gehört, aber ich versuche es am Anfang
einfacher zu halten und immer mehr zu erweitern.
Ich denke nicht das "onload" der Grund ist das es nicht funktioniert
oder liege ich da falsch?
Mfg,
Tropaion
Fabian P. schrieb:> Ich denke nicht das "onload" der Grund ist das es nicht funktioniert
Der Grund ist, dass JS hochgradig asynchron arbeitet. Wenn du JS sagst,
es soll dir deine "variables.json" holen, dann macht es das. Irgendwann.
Währenddessen läuft das Programm weiter ab, denn so ein Datenabruf kann
im Internet ja einige Zeit dauern. Wäre ja blöd, wenn währenddessen
alles blockiert wäre. Es läuft also weiter in deine functions.js, will
die "pumpe_1_mode" lesen und peng - nicht gefunden, weil die kommt erst
irgendwann in der Zukunft asynchron daher. Also dort einen check
einbauen, ob es die schon gibt, ansonsten "return". Beim Durchlauf eine
Sekunde später ist sie dann schon da.
In
$.getJSON(urlVariables, nameVariables);
ist nameVariables ein "Funktionsobjekt", d.h. ein Objekt, das den
()-Operator kennt, mit dem man das im Objekt versteckte Script ausführen
kann. $.getJSON ruft dieses dann irgendwann später auf, um die
empfangenen Daten zurückzuliegen.
PS.: seh's als Kompliment, daß ich den Schüler nicht gleich entdeckt
hab. Ich bin dir eben 35 Jahre voraus. Damals haben wir am TG noch
deutlich einfachere Dinge gemacht ;-)
Danke Basterl ;)
Das es ein Obejekt ist, ist mir glar was was meinst du mit aufrufen?
@Dirk
Global initialisiert sind sie doch eh oder?
Laut definition in W3C ist eine Variable ohne "var" in einem
Unterprogramm automatisch global
@Jan Hansen
Auch wenn das so ist, die Funktion wird ja jede Sekunde ausgeführt, das
heißt es müsste spätestens eine Sekunde nach dem Laden gehen oder nicht?
EDIT:
Ok, um ehrlich zu sein, ich bin jetzt etwas verwirrt. Hab denn Tipp von
Hansen mal ausprobiert und er funktioniert, jedoch warum ist mir
unerklärlich.
1
/** URL zur Variablendefinierung - JSON-Format */
2
var urlVariables = "./variables/variables.json";
3
var pumpe_1_mode;
4
5
function nameVariables(jd){
6
/** Variablen deklarieren */
7
temp_1 = (jd.temp_1);
8
pumpe_1_mode = (jd.pumpe_1_mode);
9
}
10
11
function updateVariables(){
12
$.getJSON(urlVariables, nameVariables);
13
}
14
/** Alle 1000ms werden die Variablen aktualisiert */
15
updateVariables();
16
setInterval(updateVariables, 1000);
Die Variable "temp_1" kann ich ja auch mit einer anderen Funktion
(Global) aufrufen, laut W3C (http://www.w3schools.com/js/js_scope.asp)
definiert man eine Variable ja auch so innerhalb einer Funktion als
Global. Warum muss ich dann pumpe_1_mode noch mal außerhalb der Funktion
deklarieren
Schau dir mal selfhtml.org an. Da kann man sich über viel Beispiele an
das Thema rantasten. Jeder vernüftige Browser erlaubt heute per F12 zu
debuggen. Viel zu tun für die Ferien ;-)
Fabian P. schrieb:> @Jan Hansen> Auch wenn das so ist, die Funktion wird ja jede Sekunde ausgeführt, das> heißt es müsste spätestens eine Sekunde nach dem Laden gehen oder nicht?
Habe den Code nicht mehr vor mir, aber wenn ich mich richtig erinnere
rufst du die Funktion initial einmal auf (Skriptfehler => Abbruch), erst
danach setzt du das Intervall (wird in diesem Fall nicht gemacht, weil
vorher der Fehler war).
Also prinzipiell hast du recht: hättest du das Intervall vor dem Fehler
gesetzt, dann hätte der nächste Durchlauf geklappt. So gibt es aber
keine weiteren Durchläufe.
Fabian P. schrieb:> @Dirk> Global initialisiert sind sie doch eh oder?> Laut definition in W3C ist eine Variable ohne "var" in einem> Unterprogramm automatisch global
Ja, aber das machst du erst später asynchron. So versucht er die globale
Variable zu lesen, die es nicht gibt. Wenn du zu Beginn "pumpe_1_mode =
null;" schreibst, dann gibt es sie und alles ist paletti.
> var pumpe_1_mode;> damit sie global ist?
Musst du eh nicht, ohne "var" passt damit sie global ist.
Jetzt funktioniert es auch ohne das die Variablen extra definiert
werden.
Kann ich das Script varUpdate.js so priorisieren, das es das erste
Script ist welches ausgeführt werden soll?
Um da mal weniger an den symptomen rumzudoktern und das alles ein
bisschen grade zu rücken:
warum rufst du nicht aus deinem update-interval (ggf. wenn du
festgestellt hast das sich etwas geändert hat) ein update des dom auf?
dann hast du das Problem gar nicht das die Daten noch nicht da sind wenn
du den dom updaten willst, und du hast deine Daten im schnitt 500ms
schneller auf dem schirm :)
Sehr interessanter Ansatz, mir kam das auch schon mal in den Sinn, aber
ich wusste nicht das das geht.
Wie heißt der Befehl mit dem das geht, bzw. nach was muss ich suchen?
Unter "Javascript dom update" finde ich nichts dazu.
Und wie kommst du darauf das es im Schnitt 500ms sind?
Danke und Mfg,
Tropaion
Na momentan hast du ja 2 Intervale die alle 1000ms dinge tun, der eine
läd Daten irgendwo her und speichert sie zwischen, der andere nimmt
diese Daten und zeigt sie an (in dem es den dom updated).
Die Zeit die vergeht zwischen dem Updaten der zwischengespeicherten
Daten und dem Anzeigen dieser ist liegt zwischen 0 und 1000ms. Wo genau
kannst du nur im Einzelfall bestimmen, und es gibt da einen Drift.
Der Mittelwert ist also ( 100 - 0 ) / 2.
Was du jetzt tun kannst: du kannst in dem interval der die Daten
einsammelt sie auch rausschreiben, am besten mit einer Prüfung ob sich
diese überhaupt geändert haben.
Grüße, Dirk
Achso, sozusagen ein Intervall mit einer anonymen Funktion wo alle
Funktionen zum Updaten einfach ausgeführt wird so unser Art:
Intervall {
varUpdate;
valueUpdate1;
valueUpdate2;
.....
}
Von der Rechnung her meinst du wahr. (1000 - 0)/2 = 500ms oder?
Danke und Mfg,
Tropaion
Ja genau, nur ein interval.
und genau so komm ich an die 500ms, jetzt hast du im schlimmsten fall
2000ms Verzögerung wenn sich ein wert ändert, beide Intervalle addieren
sich im schlimmsten fall. so hast du maximal 1000ms
Jetzt weiß ich auch was du meinst.
Wir haben mal so was ähnliches in der Schule gemacht.
Prozessor -> zyklisches Abarbeiten von Befehlen.
Meine Lösung ist jetzt:
1
<script>
2
<!--
3
/** Alle 1000ms werden die Werte aktualisiert */
4
window.onload = function() {
5
setInterval(function() {
6
/** Die zu aktualisierenden Funktionen hier eintragen */