NEWS

Bug oder Feature? getState() /= x 'cached' den State


  • Hallo
    das fiel eben durch eine Anfrage im Forum auf. getState() verhält sich dabei ähnlich wie eine Variable, wobei der Wert selbst nach Neustart des Skripts erhalten bleibt, ohne dass sich der Wert des State aber tatsächlich ändert. Ein neues Setzen des DP oder ein Neustart der Instanz(ohne Änderung des DP) beendet den Spuk
    Ein getState() mit callback liefert immer den richtigen Wert des DP!

    var DP = '0_userdata.0.Test';
     
    //setState(DP,100000);
    for(let i=0;i<2;i++) {
        log(i + ': ' + (getState(DP).val /= 10).toString());
        
        log(i + ': ' + getState(DP).val.toString());
        
        getState(DP,(err,obj) => {
            log(i + ': ' + obj.val.toString());
        })
    }
    

    ich hoffe das kann mir wer erklären
    Grüße,
    Winny


  • @fastfoot sagte:

    log(i + ': ' + (getState(DP).val /= 10).toString());                                                                                                                                                                            
    

    Du schreibst auf das Objekt zurück, was bei getState() nicht vorgesehen ist.
    Das ist deshalb möglich, da der Javascript-Adapter alle Objekte und Zustände puffert und die Reaktion auf getState(id) letztlich lautet (states ist der Puffer):

    return states[id];
    

    Da es sich um ein Objekt handelt, wird nicht der Inhalt zurück gegeben, sondern eine Referenz (Zeiger) auf das Objekt. Deshalb kann man mit

    getState(id).val /= 10
    

    den Inhalt des Objektes im Puffer verändern, was sich bei der erneuten Abfrage bemerkbar macht.
    Bei der asynchronen Version wird nicht auf den Puffer zurück gegriffen.


  • @paul53 Danke für die ausführliche Antwort, auch wenn ich erstmal nur 90% verstanden habe 🙂 Was mir aber nicht klar geworden ist, weshalb bleibt das bestehen, auch wenn das Skript gestoppt und dann wieder gestartet wird? Da sollten doch alle Zustände, Referenzen und Variablen etc. zurückgesetzt werden? Wie im LOG zu sehen ist, passiert das jedoch nicht. Starte ich nun ein zweites Skript, welches auch den Status des DP ausliest, dann wird mir auch dort der falsche Wert ausgegeben, spätestens hier plädiere ich für Bug, habe das soeben erst probiert, deshalb vorher nicht erwähnt

    Ferner, sollte so ein Statement nicht einen Fehler provozieren, da das eben nicht vorgesehen ist? Ein Statement wie

    getState(dp).val=5;
    

    sollte eigentlich nicht möglich sein, auch wenn das unter der Haube erklärbar ist.

    Zu meiner 'Verteidigung', das Statement stammt nicht von mir, ich habe nur darauf reagiert 🙂


  • @fastfoot sagte:

    sollte so ein Statement nicht einen Fehler provozieren, da das eben nicht vorgesehen ist?

    Das wäre sinnvoll, aber ich habe keine Ahnung ob / wie man das abfangen kann.

    @fastfoot sagte in Bug oder Feature? getState() /= x 'cached' den State:

    weshalb bleibt das bestehen, auch wenn das Skript gestoppt und dann wieder gestartet wird?

    Der Puffer befindet sich nicht im Script, sondern in der Javascript-Instanz, bei Neustart des Scripts wird auf den gleichen Puffer zurück gegriffen. Bei Neustart der Instanz wird der Puffer mit den Werten aus dem js-controller initialisiert.
    Mit setState() wird nicht nur der Puffer aktualisiert, sondern der Zustand auch an den js-controller weitergegeben.


  • @paul53 Deine Ausführungen kann ich nachvollziehen, ein "Ändern" durch solch ein Statement aus einer anderen Instanz hat keine Auswirkungen, aber es bleibt der Fakt dass andere Skripte hierdurch falsche Werte liefern. Sollte ich ein issue auf Github aufmachen oder ist das eher uninteressant weil nur Wenige das so proggen würden? Vielleicht mag sich auch @apollon77 das erst einmal ansehen?

    javascript.1	2020-07-03 00:12:05.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> DP wurde verfälscht durch falsches Statement in Skript1
    javascript.1	2020-07-03 00:12:04.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> DP wurde verfälscht durch falsches Statement in Skript1
    javascript.1	2020-07-03 00:12:03.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> DP wurde verfälscht durch falsches Statement in Skript1
    javascript.1	2020-07-03 00:12:02.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> DP wurde verfälscht durch falsches Statement in Skript1
    javascript.1	2020-07-03 00:12:01.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> DP wurde verfälscht durch falsches Statement in Skript1
    javascript.1	2020-07-03 00:12:00.013	info	(6899) script.js.Aktiv.JS1: Skript1: verfälsche DP durch getState() = xxx;
    javascript.1	2020-07-03 00:12:00.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> 100000
    javascript.1	2020-07-03 00:11:59.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> 100000
    javascript.1	2020-07-03 00:11:58.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> 100000
    javascript.1	2020-07-03 00:11:57.001	info	(6899) script.js.Aktiv.JS2: Skript2: DP ==> 100000
    javascript.1	2020-07-03 00:11:56.478	info	(6899) script.js.Aktiv.JS2: registered 0 subscriptions and 1 schedule
    

  • @fastfoot sagte:

    nur Wenige das so proggen würden?

    Es ist der erste Fall, den ich so sehe, also kann man davon ausgehen, dass so etwas höchstens versehentlich programmiert wird. Wie geschrieben, sehe ich keine Möglichkeit, dies abzufangen.


  • @paul53 Ich kenne mich in JS zu wenig aus, deshalb vertaue ich voll auf deine Expertise und lasse das mit dem issue sein. Nochmals vielen Dank für deine Erläuterungen, habe Einiges dazu gelernt

  • Starter

    @paul53
    Abfangen könnte man das dadurch, das man diese Variablen privatisiert und Zugriff nur über Funktionen erlaubt. Das wäre allerdings ein tiefer Eingriff in den iobroker und hat Auswirkungen auf alle Skripte und Adapter.
    Andere Alternative wäre noch eine Prüfung im Objekt-Prototyp, aber das würde dann bei jedem Variablenzugriff passieren was sich sicherlich auf die Performance auswirkt. Für iobroker dann eigene objekte schaffen wäre wiederum ein tiefer Eingriff in iobroker.


  • Ja, das ist JavaScript.
    Ich wette

    typeof (getState(dp))
    

    Liefert "function".
    Diese Funktion wir nun durch einen Wert überschrieben.
    Das Ganze verhindert Typescript. Einige Adapter haben das ja schon ...


  • @SVallant sagte:

    Ich wette
    typeof (getState(dp))
    Liefert "function".

    Die Wette verlierst Du, denn es ist ein Objekt. Da hilft auch keine Typ-Bindung.

Suggested Topics

  • 3
  • 2
  • 5
  • 5
  • 3
  • 16
  • 5
  • 10

1.8k
Online

34.9k
Users

40.9k
Topics

561.4k
Posts