Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. javascript-Adapter bindet console.log nicht ein bei require

    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

    javascript-Adapter bindet console.log nicht ein bei require

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

      Im iobroker Javascriptadaper habe ich viele Skripts, die Funktionen z.B. "function1" verwenden.
      In die "globalen Skripte (global)" sollen sie nicht hinein, da sind dann ja vor jedes Skript eingebunden werden und hier im Forum mehrfach auf die Speicherproblematik hingewiesen wurde.

      Die Methoden sind ausgelagert in die Datei modneu.js, darin zwei Consolenmeldungen zum debuggen.

      function function1 (a){
                // do some stuff
                console.log('console.log innerhalb function1');
                console.debug('console.debug innerhalb function1');
              return a+1;
          }
      exports.function1 = function1;
      

      Aufruf in main.js:

      foo = require('../../../iobroker-data/modules/modneu.js');
      console.log(foo.function1(9));
      

      Nach dem Neustart des javascripts-Adapters (nach jeder Änderung von modneu.js!) zeigt die javascriptkonsole nur die Ausgabe "10" also 9+1.
      Die Consolen-Logs zum debuggen innerhalb der requirefunktion werden nicht angezeigt.

      Nun habe ich hier im Forum gelernt, dann man iobroker-Befehle im require-scope nur nutzen kann, in dem man als zusätzlichen Parameter der Funktion this oder globalThis mit übergibt. Dies ist für mich eine gute Lösung, wenn ich iobroker-spezifische Befehle wie setState verwenden möchte.

      function function1 (a, this1){
                // do some stuff
                this1.console.log('console.log innerhalb function1');
                this1.console.debug('console.debug innerhalb function1');
              return a+1;
          }
      exports.function1 = function1;
      

      Übergabeparameter jetzt (9, this) in main.js:

      foo = require('../../../iobroker-data/modules/modneu.js');
      console.log(foo.function1(9, this));
      

      Jedoch: console.log ist ein Standard-Befehl von node.js. Dieser Befehl wird vermutlich innerhalb der javascript-adapters so umgelenkt, dass die Ausgabe schön unterhalb des Scriptfensters in iobroker zu sehen ist. Im scope von require gibt es also dieses sinnvolle adapter-spezifische console.log() nicht mehr.

      Vermutlich wird ohne this im ersten Fall eine andere console.log verwendet, die aber nicht in das iobroker-Fenster weiterleitet. Nur, wohin gehen die logs, wo kann ich den debug-Ausdruck irgendwo sonst finden?

      Bei node.js werden die console.log() Ausgaben standardmäßig auf stdout geschrieben. Daher habe ich mit: systemctl stop iobroker und dann iobroker von hand über node gestartet und die Standardausgabe von node ansehen. Negativ, ebenso keine zusätzlichen logfiles in /opt/iobroker/log. Andere logfiles habe ich nicht gefunden.

      Ich bin unsicher, ob das ein Bug ist, weil im wrapper der require-funktion die neue console.debug/info/... -Funktionen noch nicht mit eingebunden wurden und somit kein debuggen mit console.log möglich ist. Oder ist das richtig so und obiges Verhalten einfach die Konsequenz, wenn man require verwenden will, weil man keine globalen Skripte wegen des Speicherplatzes möchte?

      Oder gibt es eine einfache Lösung, die ich übersehen habe?
      Tks!

      T OliverIO 2 Replies Last reply Reply Quote 0
      • T
        ticaki Developer @Axel21 last edited by

        @axel21

        benutze doch this.log()

        A 1 Reply Last reply Reply Quote 0
        • OliverIO
          OliverIO @Axel21 last edited by

          @axel21

          Es ist nur eine Vermutung:
          Zur Ausführung der Skript wird Node:vm verwendet.
          Darin ist mehr oder weniger alles gekapselt.
          Wahrscheinlich ist das console Objekt umgeleitet.
          Was aber in deinem Fall mit require dann wohl nicht mehr funktioniert.
          Ich habe leider vergeblich versucht im Source was zu finden.
          Es gibt noch den Log Befehl. Leider ist dieser in der adapterdokumentation häufig erwähnt, aber nicht dokumentiert. Versuche es mal damit.

          1 Reply Last reply Reply Quote 0
          • A
            Axel21 @ticaki last edited by

            @ticaki
            Vielen Dank für die schnelle Antwort.
            Im Hauptprogramm funktioniert log('logtext') mit der Ausgabe auf die iobroker - Console.

            Im require-scope funktioniert bei mir weder this.log('logtext') noch log('logtext').
            Beides Mal gibt es eine Fehlermeldung "this.log is not a function" bzw. "log is not a function".
            Unter node.js gibt es log(' ') nicht. Daher ist das Verhalten für mich nachvollziehbar.

            Anders als console.log ist log wohl eine rein iobroker-Funktion, die es im require-scope nicht mehr gibt.
            Daher funktionier this1.log('text'), genauso wie this1.console.log('text); im zweiten Beispiel.
            Aber dazu muss dann eben wieder this übergeben werden.

            Leider ist das keine Lösung. Danke dennoch!

            OliverIO T 2 Replies Last reply Reply Quote 0
            • OliverIO
              OliverIO @Axel21 last edited by OliverIO

              @axel21

              Nach dem Beispiel von oben müsste es

              this1.log

              heißen.
              Log ist ein Befehl des JavaScript Adapters

              Hier der link zur typdefinition von Log
              https://github.com/ioBroker/ioBroker.javascript/blob/dcc86d319d6e9b5a5e2f0ae6c93c9e7814df35f3/src/lib/javascript.d.ts#L1144

              Direkt darunter sieht man auch die Umleitung von console.
              Also ist console nun auch Bestandteil des globalen Objekts

              Wenn du vor console immer dein this1 davor schreibst funktioniert es.

              Also
              this1.console.log(.....

              Das Konzept nennt sich shadowing
              https://www.geeksforgeeks.org/javascript/variable-shadowing-in-javascript/

              In JavaScript ist ja nix geschützt. Auch interne Funktionen können überschrieben werden oder erweitert werden. Da gibt es schöne Beispiele wie bspw das String Objekt mit weiteren Funktionen erweitern , die exakt so angewendet werden können wie die bereits eingebauten.

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

                @axel21
                Ich denke wie @OliverIO das du nicht this1.log() verwendet hast, falls doch.

                kannst du auch die log funktion übergeben und diese Verwenden.

                function function1 (a, this1, log){
                          // do some stuff
                          log('console.log innerhalb function1');
                          log('console.debug innerhalb function1');
                         return a+1;
                     }
                 exports.function1 = function1;
                
                foo = require('../../../iobroker-data/modules/modneu.js');
                console.log(foo.function1(9, this, log));
                
                OliverIO 1 Reply Last reply Reply Quote 0
                • A
                  Axel21 @OliverIO last edited by

                  @oliverio
                  Danke, da haben sich die Posts zeitlich überschnitten.

                  Nochmal in Kürze:
                  Es existiert ein Workaround, ich komme also zurecht.
                  a) Aufrufende Funktion um ", this" ergänzen
                  b) Aufgerufene Funktion um ", this1" ergänzen.
                  c) this1.console.log oder this1.log verwenden.

                  Das finde ich reichlich umständlich für ein console.log() zum debuggen.

                  Außerdem von der Systematik her:
                  console.log schreibt im require-scope "irgendwo" hin, nur wohin???
                  Wäre es dann nicht sinnvoll, die neue iobroker console.log in diesen require scope im Adapter im wrapper mit einzubinden, so dass auch im require-scope in den iobroker geloggt wird?

                  Dann erst wäre das Verhalten von iobroker-javascript identisch mit dem node.js bezüglich console.log.
                  In node logt console.log sowohl im main-prg als auch im require-scope an die gleiche Ausgabe (weil statische globale Funktion) .

                  Soweit zur Erläuterung hope that helps.
                  Tks!

                  T OliverIO 2 Replies Last reply Reply Quote 0
                  • T
                    ticaki Developer @Axel21 last edited by ticaki

                    @axel21
                    Du kannst doch auch

                    function bla(this1) {
                      const console = this1.console;
                      //...
                      console.log('geht... yeah! :)');
                    }
                    

                    an den anfang schreiben 🙂

                    A 1 Reply Last reply Reply Quote 0
                    • OliverIO
                      OliverIO @ticaki last edited by

                      @ticaki

                      Doch, genau this1.log meine ich.
                      Er übergibt an seine Funktion ja das globale Objekt des JavaScript Adapters.
                      Dort ist console und log entsprechend definiert.
                      Wenn er es dann in seinen eingebauten Funktionen verwenden will, muss er das entsprechend immer voranschreiten.

                      Jetzt etwas hacking, was ich auch noch nicht probiert habe.

                      global ist die variable die den aktuellen globalen context enthält.
                      Wenn er nun versucht am Anfang einer Funktion bspw mit

                      global = this1;

                      Diesen globalen context zu korrigieren, dann müsste
                      console.log wieder funktionieren.

                      Aber keine Ahnung ob global beschreibbar ist.

                      1 Reply Last reply Reply Quote 0
                      • OliverIO
                        OliverIO @Axel21 last edited by

                        @axel21

                        Ich vermute, das mit require ein normaler und nicht der vm context erzeugt wird. In diesem sind die ganzen funktionsdefinitionen und Umleitungen aber nicht mehr vorhanden. Daher muss man diese Korrekturen umsetzen.

                        Ideal wäre es nun, wenn der require Befehl für den JavaScript Adapter ebenfalls erweitert wird, so das er dort auch den JavaScript context mit bereitstellt.

                        Probiere mal das mit dem zuweisen zur variable global. Wenn das funktioniert,
                        Könnte ich dir einen workaround zeigen, bei dem man nach require nur einen Befehl ausführen muss um dann alles ganz normal zu verwenden.

                        A 1 Reply Last reply Reply Quote 0
                        • A
                          Axel21 @ticaki last edited by

                          @ticaki
                          Ok Danke für diesen Tipp.
                          Der Post läuft gerade in eine andere Richtung als gedacht.

                          Ich habe drei Lösungen wie ich im require-scope ein log in die iobroker-console loggen kann.
                          Alle diese Lösungen erfordern das übergeben von "this" über die Funktion.

                          Für mich ist dieser Teil abgeschlossen.

                          Offen bleibt für mich und darum geht es mir:
                          Ist es so richtig im iobroker-javascript-Adapter implementiert?
                          Ist es so gewollt, dass die Ausgabe eines einfachen console.log im require-scope ohne this-trick - im nirgendwo landet?
                          Ist es gewollt, dass console.log im main und im require-scope an unterschiedliche Stellen (iobroker-console vs. nirgendwo) hinloggen.
                          Ist es gewollt, dass die iobroker-javascript-engine sich hier anders verhält als ein andere engine (hier node.js). Hier bekomme ich in beiden scopes das logging an die gleiche Stelle und kann es dort lesen.

                          Das ist meine Frage. Wenn die erfahrenen Leute hier sagen: "Ist so ok", dann -> closed.

                          1 Reply Last reply Reply Quote 0
                          • A
                            Axel21 @OliverIO last edited by

                            @oliverio
                            Zu Deinem Trick mit "global". Eben ausprobiert:

                            function function1 (a,this1) {
                                global=this1;
                                this1.console.log('innerhalb function1 this1.console.info'); // wird geloggt
                                console.log('innerhalb function1 mit global-Trick'); // wird leider ins nirgendwonicht geloggt
                            return a+1;
                            }
                            exports.function1 = function1;
                            
                            

                            mit Aufruf

                            foo = require('../../../iobroker-data/modules/modneu.js');
                            console.log(foo.function1(9, this));
                            

                            Leider nein: Aber einen solchen Hack hatte ich bei java vor jahren einmal. Mit einigen (internen und problematischen) Funktionen war es meiner Erinnerung nach möglich, den Kontext der aufrufenden Funktion zu ermitteln. War nicht lehrbuchgemäß, hatte aber funktioniert.

                            Danke dennoch, jetzt wissen wir, dass es so nicht geht.
                            Und wenn kein Erfahrener hier meint, dass man das an die javascript-Adapter-Leute weitermelden soll, dann ist es auch für mich gut.
                            Danke nochmals an alle, die bisher mitgedacht haben.

                            OliverIO 1 Reply Last reply Reply Quote 0
                            • OliverIO
                              OliverIO @Axel21 last edited by

                              @axel21

                              Gut, workaround ist da, ich werde bei Gelegenheit selber mal experimentieren.

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

                              Support us

                              ioBroker
                              Community Adapters
                              Donate

                              716
                              Online

                              31.9k
                              Users

                              80.1k
                              Topics

                              1.3m
                              Posts

                              javascript
                              3
                              13
                              48
                              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