NEWS
javascript-Adapter bindet console.log nicht ein bei require
-
benutze doch
this.log()
-
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. -
@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!
-
Nach dem Beispiel von oben müsste es
this1.log
heißen.
Log ist ein Befehl des JavaScript AdaptersHier der link zur typdefinition von Log
https://github.com/ioBroker/ioBroker.javascript/blob/dcc86d319d6e9b5a5e2f0ae6c93c9e7814df35f3/src/lib/javascript.d.ts#L1144Direkt darunter sieht man auch die Umleitung von console.
Also ist console nun auch Bestandteil des globalen ObjektsWenn 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.
-
@axel21
Ich denke wie @OliverIO das du nichtthis1.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
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! -
@axel21
Du kannst doch auchfunction bla(this1) { const console = this1.console; //... console.log('geht... yeah! :)'); }
an den anfang schreiben
-
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 mitglobal = this1;
Diesen globalen context zu korrigieren, dann müsste
console.log wieder funktionieren.Aber keine Ahnung ob global beschreibbar ist.
-
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. -
@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.
-
@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. -
Gut, workaround ist da, ich werde bei Gelegenheit selber mal experimentieren.