Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. getObject setObject BUG?

    NEWS

    • Neuer Blog: Fotos und Eindrücke aus Solingen

    • ioBroker@Smart Living Forum Solingen, 14.06. - Agenda added

    • ioBroker goes Matter ... Matter Adapter in Stable

    getObject setObject BUG?

    This topic has been deleted. Only users with topic management privileges can see it.
    • J
      j1s2e3 last edited by

      Ich habe ein komisches Verhalten. Sieht wie ein race/concurrency bug aus.

      Folgendes zum reproduzieren:

      2 Datenpunkte unter 0_userdata anlegen:
      // 0_userdata.0.test.test1
      // 0_userdata.0.test.test2
      beide sind im meinem Fall vom Typ device

      1 Raum unter Aufzählungen->Rooms anlegen
      // enum.rooms.test
      id ist test

      dann dieses Skipt ausführen:

      function add2Enum(id, name) {
          let r = getObject(id);
          if (!r.common.members.includes(name)) {
              r.common.members.push(name);
              log('add2Enum: adding ' + name + ' to enum ' + id, 'info');
              setObject(id, r, function (err) {
                  if (err) log('add2Enum: adding ' + name + ' to enum ' + id + ' - error=' + err, 'error');
              });
          }
      }
      
      add2Enum('enum.rooms.outdoors', '0_userdata.0.test.test1');
      add2Enum('enum.rooms.outdoors', '0_userdata.0.test.test2');
      

      Skipt soll DP einem Raum zuordnen. Wenn ich beide Aufrufe add2Enum ausführe, dann wird nur test2 dem Raum test zugeordnet. test1, also der erste Aufruf von add2Enum(), nicht. Einzelne Aufrufe, oder zeitlich entzerrte Aufrufe gehen.
      setObject läuft ohne Fehler durch. Hier das Log:

      14:18:20.860	info	javascript.0 (25948) Stop script script.js.common.VirtualDevices.set-get-test
      14:18:26.922	info	javascript.0 (25948) Start javascript script.js.common.VirtualDevices.set-get-test
      14:18:26.930	info	javascript.0 (25948) script.js.common.VirtualDevices.set-get-test: add2Enum: adding 0_userdata.0.test.test1 to enum enum.rooms.test
      14:18:26.931	info	javascript.0 (25948) script.js.common.VirtualDevices.set-get-test: add2Enum: adding 0_userdata.0.test.test2 to enum enum.rooms.test
      14:18:26.931	info	javascript.0 (25948) script.js.common.VirtualDevices.set-get-test: registered 0 subscriptions and 0 schedules
      

      Es scheint so, als ob das setObject für test1 noch nicht abgeschlossen, in die DB geschrieben, ist, wenn im 2. Aufruf von add2Enum() wieder getObject() auf die gleiche id gemacht wird. Das 2. getObject('enum.rooms.outdoors') liefert noch den Zustand vor dem setObject zurück, als test1 noch nicht member von enum.rooms.test war. D.h. obwohl das setObject für test1 erfolgreich war und aus Skript-Sicht abgeschlossen ist, liefert ein zeitlich nahes erneutes getObject, nicht den Zustand zurück, der eben via setObject definiert wurde.

      Wenn ich das Objekt r vom 2. getObject() dumpe, dann ist test1 definitiv nicht unter r.members enthalten.

      Für mich sieht das nach einem Bug aus. In der Javascriptdoku steht auch nichts, dass man nach setObject noch irgendein commit oder sonstwas machen sollte.

      F 1 Reply Last reply Reply Quote 0
      • F
        fastfoot @j1s2e3 last edited by

        @j1s2e3 sagte in getObject setObject BUG?:

        Für mich sieht das nach einem Bug aus.

        für mich sieht das aus als wärst du in die asynch-Falle getappt. setObject() arbeitet asynchron, das heißt ein Ergebnis wird irgendwann geliefert, in dem Fall nachdem du bereits den 2ten Aufruf gestartet hast. Im Folgenden wird gewartet bis der erste Aufruf beendet ist.

        async function add2Enum(id, name) {
            let r = getObject(id);
            if (!r.common.members.includes(name)) {
                r.common.members.push(name);
                await setObjectAsync(id, r);
                return true;
            }
            return false;
        }
        
        async function main() {
            let res = false;
            res = await add2Enum('enum.rooms.living_room', '0_userdata.0.Forum.test.t1')
            if (res) log('add2Enum: adding ' + '0_userdata.0.Forum.test.t1' + ' to enum ' + 'enum.rooms.living_room' + ' finished', 'info');
        
            res = await add2Enum('enum.rooms.living_room', '0_userdata.0.Forum.test.t2')
            if (res) log('add2Enum: adding ' + '0_userdata.0.Forum.test.t2' + ' to enum ' + 'enum.rooms.living_room' + ' finished', 'info');
        }
        
        main()
        
        T J 2 Replies Last reply Reply Quote 1
        • T
          ticaki Developer @fastfoot last edited by

          @fastfoot
          Ich würde getObjectAsync() auch noch verwenden, aber nicht nötig

          F 1 Reply Last reply Reply Quote 0
          • J
            j1s2e3 @fastfoot last edited by

            @fastfoot Danke für die Erklärung! Aber woher sollte ich wissen, dass setObject asynchron ist. In der Doku auf github steht da nix zu??? Gibt es irgendwo noch eine "bessere" Doku?

            In deinem Beispiel nimmst Du setObjectAsync(). Da würde ich von einem asynchronem Verhalten ausgehen. Suggeriert ja der Name schon. Aber setObjectAsync() ist wird in der Github-Doku nichtmal erwähnt und die Doku auf Github ist die einzige, welche ich bisher als API-Doku gefunden habe. Welche Doku nimmst Du denn?

            Was ist dann der Unterschied zw. setObject() und setObjectAsync()? Keiner?

            F 1 Reply Last reply Reply Quote 0
            • F
              fastfoot @j1s2e3 last edited by

              @j1s2e3 wenn eine Funktion einen Callback hat ist sie grundsätzlich asynchron. Auch die...Async Funktionen sind erst einmal asynchron(sic!), denn sie liefern ein Promise zurück welches auch nur ein 'Versprechen in die Zukunft' ist. Das synchrone Verhalten erreicht man erst durch await, welches auf die Erfüllung dieses Versprechens wartet. Das beantwortet dann auch deine Frage ob die beiden Funktionen denn gleich sind 🙂

              Mit der Doku ist das so eine Sache, die ist auch irgendwie asynchron und liefert ein Versprechen, in der Zukunft gut und vollständig zu sein 🙂

              1 Reply Last reply Reply Quote 2
              • F
                fastfoot @ticaki last edited by

                @ticaki sagte in getObject setObject BUG?:

                @fastfoot
                Ich würde getObjectAsync() auch noch verwenden, aber nicht nötig

                da gibt es keinen Grund dazu. Die xxxAsync Funktionen im JS-Adapter sind Versionen der Funktionen ohne Async, welche promisified wurden, um callback-style Funktionen in Promises zu wandeln. Das macht aber nur Sinn wenn man sie mit await verwenden will, was im Falle von getObject() aber nicht notwendig ist, da es hier ohne callback verwendet wird. Oder anders gesagt, das schafft nur overhead, keinen Mehrwert(imho!)

                T 1 Reply Last reply Reply Quote 0
                • T
                  ticaki Developer @fastfoot last edited by

                  @fastfoot
                  Es macht Sinn da die ganze Funktion in dem Fall ohne abonnierte States funktioniert. 😉 Ich weiß halt nur nicht, wieso man die nicht abonnieren sollte.

                  paul53 F 2 Replies Last reply Reply Quote 0
                  • paul53
                    paul53 @ticaki last edited by paul53

                    @ticaki sagte: wieso man die nicht abonnieren sollte.

                    Wenn man die States / Objekte abonniert, werden sie mit den synchronen Funktionen aus dem Puffer der Javascript-Instanz geholt, andernfalls aus dem js-controller.

                    1 Reply Last reply Reply Quote 0
                    • F
                      fastfoot @ticaki last edited by

                      @ticaki sagte in getObject setObject BUG?:

                      @fastfoot
                      Es macht Sinn da die ganze Funktion in dem Fall ohne abonnierte States funktioniert. 😉 Ich weiß halt nur nicht, wieso man die nicht abonnieren sollte.

                      der TE hat die States aber nunmal abonniert 🙂

                      T 1 Reply Last reply Reply Quote 0
                      • T
                        ticaki Developer @fastfoot last edited by ticaki

                        @fastfoot
                        Das Lesen mehr Leute als nur der TE und ich hätte mir viel ausprobieren erspart, wenn manches vollständiger ausgeführt würde. Doku gibts ja teilweise nur als versprechen. 🙂

                        1 Reply Last reply Reply Quote 0
                        • First post
                          Last post

                        Support us

                        ioBroker
                        Community Adapters
                        Donate

                        673
                        Online

                        31.8k
                        Users

                        80.0k
                        Topics

                        1.3m
                        Posts

                        4
                        10
                        481
                        Loading More Posts
                        • Oldest to Newest
                        • Newest to Oldest
                        • Most Votes
                        Reply
                        • Reply as topic
                        Log in to reply
                        Community
                        Impressum | Datenschutz-Bestimmungen | Nutzungsbedingungen
                        The ioBroker Community 2014-2023
                        logo