Forum: PC-Programmierung Javascript ist zu schnell


von Kilian K. (kellermaaan)


Lesenswert?

Hallo an alle,

ich habe ein kleines Problem mit meinem Javascript...
1
function startTest() {
2
  "use strict";
3
  var request = false,
4
    i = 0,
5
    timeToWait = 0;
6
  
7
  function frequencyComplete() {
8
        if (request.readyState === 4) {
9
            if (request.status === 200) {
10
        var data = JSON.parse(request.responseText);
11
        
12
        timeToWait = data.DelayTime;
13
            }
14
        }
15
    }
16
  
17
  request = new XMLHttpRequest();
18
  if (request) {
19
    request.open("GET", "/getfrequency?id=" + Math.random(), true);
20
    request.onreadystatechange = frequencyComplete;
21
    request.send(null);
22
  }
23
  
24
  function testComplete() {
25
        if (request.readyState === 4) {
26
            if (request.status === 200) {
27
        var data = JSON.parse(request.responseText);
28
        
29
        changeDosingPointColor(i, data.Auswertung);
30
            }
31
        }
32
    }
33
  
34
  for (i = 0; i < 50; i += 1) {
35
    request = false;
36
    request = new XMLHttpRequest();
37
    if (request) {
38
      request.open("GET", "/starttest?id=" + Math.random(), true);
39
      request.onreadystatechange = testComplete;
40
      request.send(null);
41
    }
42
    setTimeout(timeToWait);
43
  }
44
  
45
  getTestTableValues();
46
}

Mit dieses Funktion möchte ich 50 mal einen Vorgang auf einem Arrduino 
auslösen. Der wertet dann eine bestimmte Zeit einen analogen Eingang aus 
und schickt dann ein "Gut" (1) oder ein "Schlecht" (0) zurück. Mit 
diesem Ergebnis sollen dann Punkte grün oder rot gefärbt werden.

Ich habe aber die Vermutung, dass das Script zu schnell ist. Wenn ich 
das so ausführe wird gar nichts gefärbt aber wenn ich das z.B. mit 
Firefox debugge dann werden die Kreise gefärbt.

Ich habe schon versucht mir die Frequenz (max. 20 Hz) vom Arduino vorher 
zu holen und damit dann ein setTimeout zu machen aber das hilft auch 
irgendwie nicht. In "timeToWait" steht dann gerne mal nichts drin, also 
eine 0.

Ich hoffe hier ist jemand der mir dabei helfen kann das Problem zu 
lösen.

MfG Kilian

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

Die Funktion setTimeout funktioniert nicht so, wie Du Dir das denkst.

http://www.w3schools.com/jsref/met_win_settimeout.asp

von bluppdidupp (Gast)


Lesenswert?

setTimeout() erwartet doch eigentlich eine JS-Funktion und die Wartezeit 
in ms als Parameter? Du scheinst es hier als ne Art Sleep() nutzen zu 
wollen  - Das wird so vermutlich gar keinen Effekt haben?

Außerdem läuft deine for-Schleife bereits, wenn die Antwort von 
getfrequency noch gar nicht angekommen sein dürfte und timeToWait wird 
zunächst dann den Standardwert 0 haben.

request.send() arbeitet nicht synchron! D.h. der nachfolgende JS-Code 
läuft direkt weiter und die frequencyComplete-Funktion wird erst 
"mittendrin" aufgerufen, sobald die Antwort vom Server da ist.

von Carl D. (jcw2)


Lesenswert?

Falls du nicht wirklich alles Löw-Level machen willst, Les dich mal hier 
ein:
http://www.w3schools.com/jquery/jquery_ajax_intro.asp
Da sind viele der JS-Gemeinheiten versteckt.

Hier schon mal was zum durchknobeln:
1
<!DOCTYPE html>
2
<html>
3
<head>
4
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
5
<script>
6
$(document).ready(function(){
7
    $("button").click(function(){
8
        $("#div1").load("demo_test.txt", function(responseTxt, statusTxt, xhr){
9
            if(statusTxt == "success")
10
                alert("External content loaded successfully!");
11
            if(statusTxt == "error")
12
                alert("Error: " + xhr.status + ": " + xhr.statusText);
13
        });
14
    });
15
});
16
</script>
17
</head>
18
<body>
19
20
<div id="div1"><h2>Let jQuery AJAX Change This Text</h2></div>
21
22
<button>Get External Content</button>
23
24
</body>
25
</html>
Wichtig für's Verständnis: $() selektiert Element aus deiner Seite. 
"#div1" z.B. das Element mit der Id "div1" (Achtung Id und Name eines 
Elements sind Unterschiedliche Dinge).
Zu deinem Problem: AJAX ist asynchron (sonst würde es SJAX gennant 
werden), d.h. der Arduino darf sich mit der Antwort auf getfrequency 
ruhig Zeit lassen und dann Antworten. Innerhalb des gleichen 
TCP-/http-/... Requests. Ich gehe mal davon aus, daß auf dem Arduino ein 
rudimentärer http-Server läuft. Wenn nicht, dann hat JS im Browser eh 
wenig Chancen.

von Kilian K. (kellermaaan)


Lesenswert?

Erstmal danke für eure Antworten!

Carl D. schrieb:
> Ich gehe mal davon aus, daß auf dem Arduino ein
> rudimentärer http-Server läuft. Wenn nicht, dann hat JS im Browser eh
> wenig Chancen.

Jap auf dem Arduino läuft der lwIP Stack mit einem Webserver.

Da ich aber leider noch nicht so in Javascript bewandert bin, fällt mir 
so jetzt nicht wirklich eine Lösung ein :/ Wie könnte ich das denn 
umschreiben damit z.B. alles nach einer Antwort vom Arduino weiter 
abgearbeitet wird?

von Kilian K. (kellermaaan)


Lesenswert?

Habe es glaub ich hinbekommen!
1
function startTest() {
2
  "use strict";
3
  var request = false,
4
    i = 0,
5
    s = 0,
6
    timeToWait = 0,
7
    data = 0;
8
  
9
10
  function sleep(milliseconds) {
11
    var start = new Date().getTime();
12
    for (s = 0; s < 1e7; s += 1) {
13
      if ((new Date().getTime() - start) > milliseconds) {
14
        break;
15
      }
16
    }
17
  }
18
19
  request = new XMLHttpRequest();
20
  if (request) {
21
    request.open("GET", "/getfrequency?id=" + Math.random(), false);
22
    request.send(null);
23
  }
24
  
25
  if (request.readyState === 4) {
26
    if (request.status === 200) {
27
      data = JSON.parse(request.responseText);
28
      timeToWait = data.DelayTime;
29
    }
30
  }
31
  
32
  for (i = 0; i < 50; i += 1) {
33
    request = false;
34
    request = new XMLHttpRequest();
35
    if (request) {
36
      request.open("GET", "/starttest?id=" + Math.random(), false);
37
      request.send(null);
38
    }
39
    
40
    if (request.readyState === 4) {
41
      if (request.status === 200) {
42
        data = JSON.parse(request.responseText);
43
        
44
        changeDosingPointColor(i, data.Auswertung);
45
      }
46
    }
47
    sleep(timeToWait);
48
  }
49
  
50
  getTestTableValues();
51
}

Ich habe aus dem asynchrone einen synchrone request gemacht und meine 
eigene sleep Funktion geschrieben.

von Carl D. (jcw2)


Lesenswert?

Wenn du aber ernsthaft was mit Web-Oberflächen machen willst, dann 
solltest du dich in das "asynchrone" Konzept von JS/WebBrowser 
einarbeiten. Probier mal den Code aus dem jquery Tutorial (siehe oben) 
aus. Ersetze in der Zeile:
$("#div1").load("demo_test.txt", function(responseTxt, statusTxt, xhr){
die URL "demo_test.txt" durch deine "/getfrequency/id=...", dann sollte 
bei Knopfdruck das JSON-Ergebnis auf dem Browser auftauchen.
Mit deinem sleep machst du die ganze Browser-UI kaput, nennt sich auch 
"busy wait" und krallt sich einen CPU-Core.

von beric (Gast)


Lesenswert?

Kilian K. schrieb:
> meine eigene sleep Funktion geschrieben.

Das ist aber nicht der richtige Ansatz. Besser ist so lange warten mit 
dem senden des nächsten Requests bis die Antwort vom vorherigen Request 
eingetroffen ist.
1
function startTest() {
2
    "use strict";
3
    var request = false,
4
        i = 0,
5
        timeToWait = 0;
6
7
        
8
    function sendRequest(url, callback) {
9
        request = new XMLHttpRequest();
10
        if (request) {
11
            request.open("GET", url + "?id=" + Math.random(), true);
12
            request.onreadystatechange = callback;
13
            request.send(null);
14
        }
15
    }
16
17
    function testComplete() {
18
        if (request.readyState === 4) {
19
            if (request.status === 200) {
20
                var data = JSON.parse(request.responseText);
21
22
                changeDosingPointColor(i, data.Auswertung);
23
                
24
                i ++;
25
                if(i < 50) {
26
                    /* noch nicht alle tests durch? Dann nächster Test */
27
                    sendRequest("startTest", testComplete);
28
                }
29
            }
30
        }
31
    }
32
    
33
    function frequencyComplete() {
34
        if (request.readyState === 4) {
35
            if (request.status === 200) {
36
                var data = JSON.parse(request.responseText);
37
38
                /* TUE WAS MIT DATA */
39
                
40
                sendRequest("startTest", testComplete)
41
            }
42
        }
43
    }
44
45
    sendRequest("getfrequency", frequencyComplete);
46
    getTestTableValues();
47
}

von beric (Gast)


Lesenswert?

ah... Fehler entdeckt: getTestTableValues() soll natürlich im else-Zweig 
der if(i < 50) Abfrage stehen, nicht einfach am Ende der startTest() 
Funktion.
1
                if(i < 50) {
2
                    /* noch nicht alle tests durch? Dann nächster Test */
3
                    sendRequest("startTest", testComplete);
4
                } else {
5
                    /* sonst fertig ... */
6
                    getTestTableValues();
7
                }
8
...
9
    sendRequest("getfrequency", frequencyComplete);
10
}

von Kilian K. (kellermaaan)


Lesenswert?

beric schrieb:
> Das ist aber nicht der richtige Ansatz. Besser ist so lange warten mit
> dem senden des nächsten Requests bis die Antwort vom vorherigen Request
> eingetroffen ist.

Hi beric, danke, ich habe es so mal geändert und ausporbiert und es 
klappt wunderbar!

von beric (Gast)


Lesenswert?

Kilian K. schrieb:
> Hi beric, danke, ich habe es so mal geändert und ausporbiert und es
> klappt wunderbar!

Das freut mich. Ich habe es nämlich nicht getestet gehabt :-D
Aber verstehst du auch warum es funktioniert?

von Kilian K. (kellermaaan)


Lesenswert?

beric schrieb:
> Das freut mich. Ich habe es nämlich nicht getestet gehabt :-D
> Aber verstehst du auch warum es funktioniert?

Jap, ich verstehe es. Ist ja eigentlich auch recht simpel :-D

von Denkanstoßer (Gast)


Lesenswert?

Warum eigentlich "===", ist das besser als "=="?
Ist mir nur beim schnellen Durchscrollen ins Auge gestochen.

mfg

von Daniel A. (daniel-a)


Lesenswert?

Denkanstoßer schrieb:
> Warum eigentlich "===", ist das besser als "=="?

der == operator vergleicht die Rückgabewerte von valueOf, === vergleicht 
auch den typ, und {}==={} ist immer false.

Folgendes gibt true aus:
alert({valueOf:function(){return 13;}}==13)

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.