Datenaustausch mit Modulen

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • Datenaustausch mit Modulen

    Hi.

    Ich möchte mein Projekt auf mehrere Quellcodedateien aufteilen und diese dann einbinden. So wie man es bei PHP gerne mit Include macht.

    Ich habe also eine Datei main.js erstellt und eine Datei mymodule.js
    mymodule.js wird per require eingebunden und einige Variablen werden exportiert.

    Dabei ist mir aufgefallen, dass primitive Werte nur jeweils im lokalen Bereich gelten. In dem Moment, wo exports.test2 gemacht wird, steht im Hauptprogramm eine Kopie der Variable zur Verfügung. Nachträgliche Änderungen der Variable wirken sich aber nur jeweils auf den lokalen Bereich aus.
    Ändere ich beispielsweise im Hauptprogramm den Inhalt der exportierten Variable, gilt diese Änderung nur dort. Innerhalb des Moduls wird der dortige Wert verwendet.
    Außerdem ist es nicht möglich, vom Modul aus auf Variablen aus dem Hauptprogramm zuzugreifen und zu ändern.

    Richtige "Globale" Variablen, die überall gelten, wie z.B. bei PHP, gibt es offensichtlich nicht.

    Eine Möglichkeit, primitive Werte zwischen Hauptprogramm und Modul auszutauschen, sind Funktionen. Dort kann man den Wert beim Funktionsaufruf mitgeben. Und man kann mit Return Werte an das Hauptprogramm zurückgeben.

    Eine zweite Möglichkeit wäre die Verwendung eines Objektes, welches dann exportiert wird.
    Auf dieses Objekt kann ich vom Hauptprogramm aus zugreifen und Werte ändern. Die kommen dann auch im Modul an.

    Der Nachteil ist, ich muss jedes Modul dann mit die Daten füttern, und kann nicht einfach wie bei PHP einen globalen "Datenpool" haben, der dann überall zugreifbar ist.
    Gibt es denn eine Möglichkeit, ein wirklich globales Datenspeicher Objekt zu erzeugen?

    LG
  • Meine Lösung, die mir für den einfachen Datenaustausch zwischen Hauptprogramm und meinen Modulen eingefallen ist, sieht momentan so aus:

    Hauptprogramm:
    var glob={};
    glob.value="foo";

    var mymod = require('./mymodule.js');
    mymod.init(glob);


    Modul:
    var glob={}
    exports.init = function (obj) {
    glob=obj;
    glob.value2="bar";
    console.log(glob);
    }

    Also Funktion, welcher mein "Globales" Objekt im Modul verfügbar macht.

    Darin kann ich dann Projektweit allgemeine Werte speichern und relativ einfach von überall darauf zugreifen wie man es von PHP gewohnt ist.


    Oder gäbe es eine bessere lösung?
  • Ich bin mir nicht ganz sicher, wo das Problem liegen soll. Module sind Singletons. Egal wie oft Sie aufgerufen und Modifiziert werden, ihr Inhalt ist an jeder Stelle der gleiche.

    Dein Beispiel tut mir ehrlich gesagt auch etwas in den (JS verwöhnten) Augen weh:

    Tobo schrieb:

    var glob={};
    glob.value="foo";
    Erst initialisieren und im Anschluss befüllen? Das geht ja wohl auch in einem Schritt:

    JavaScript-Quellcode

    1. const glob = {
    2. value: 'foo'
    3. }






    Tobo schrieb:

    var glob={}
    exports.init = function (obj) {
    glob=obj;
    Wenn du der Variable sowieso neu zuweist, braucht sie ja wohl kaum mit einem Objekt initialisiert zu werden:

    JavaScript-Quellcode

    1. let glob
    2. function init(obj) {
    3. glob = obj
    4. }
    Zudem verwirfst du mit jedem Aufruf von init alle bisherigen Werte. Sollte nicht eher das bestehende Objekt modifiziert werden?

    JavaScript-Quellcode

    1. const glob = {}
    2. function init(obj) {
    3. Object.assign(glob, obj)
    4. }


    Meine Lösung für die selbe Funktionalität:


    JavaScript-Quellcode: main.js

    1. const mymod = require('./mymodule.js')
    2. mymod.glob.value = 'foo'
    3. mymod.print()

    JavaScript-Quellcode: mymodule.js

    1. const glob = {
    2. value2: 'bar'
    3. }
    4. function print() {
    5. console.log(glob)
    6. }
    7. module.exports = {
    8. glob,
    9. print
    10. }
    Alles anzeigen
  • Hi.

    Danke für die Tipps.

    Aber es ist leider nicht möglich, im Hauptprogramm eine Variable zu definieren und darauf vom Modul aus zuzugreifen.
    Der Wert müsste vom Hauptprogramm aus in die exportierte Variable des Moduls zugewiesen werden.

    Ich würde gerne im Hauptprogramm einige Werte definieren, die dann von jedem Modul gelesen werden können, ohne dass man sie erst vom Hauptprogramm aus an das Modul übergeben muss. Und auch die Möglichkeit, Daten Modulübergreifend auszutauschen.


    LG
  • Es gibt da noch das global-Objekt:

    JavaScript-Quellcode: main.js

    1. global.myStore = {
    2. test: 'foo'
    3. }
    4. require('./mymodule.js')

    JavaScript-Quellcode: mymodule.js

    1. if (!('myStore' in global)) {
    2. global.myStore = {}
    3. }
    4. global.myStore.value2 = 'bar'
    5. console.log(global.myStore)

    Aber sowohl Status behaftet zu arbeiten, als auch das globale Objekt zu modifizieren, sind ganz schlechte Praxis. Normalerweise versucht man möglichst stateless und nebenwirkungsfrei zu arbeiten (das Globale Objekt zu modifizieren ist definitiv eine Nebenwirkung). Falls man doch mal was speichern muss, verwendet man üblicher weise ein storage-Module. Für einen einzelnen Prozess geht auch mal "in-memory" (wie in meinem ersten Beispiel). Für komplexeres verwendet man einen zusätzlichen store (wie redis) oder eine Datenbank.

    Versuch bitte nicht deine PHP Kenntnisse nach JS zu übertragen. Das geht zwangsläufig schief.
  • Danke.

    Wie würde man denn professionell z.B folgende Beispiel-Situation meistern?

    Im Hauptprogramm wird ein Konfigurationsobjekt aus einer JSON Datei eingelesen, das enthält z.B. den Server Namen.
    Weitere Werte werden ebenfalls ermittelt und dem Objekt hinzugefügt. (z.B. __dirname)

    Dieses Konfigurationsobjekt muss nun auf die Module "Filereader" und "Webserver" verteilt werden.

    Würde man hingehen, und jedes der beiden Module die Konfiguration selbst einlesen lassen?

    Oder würde man für das Modul relevante Konfigurationsteile über eine Setter Funktion übergeben?

    Und wie würde man eine Kommunikation zwischen Filereader und Webserver ermöglichen?
    Die eingelesene Date muss ja auch irgendwie zum Webserver-Modul kommen.

    LG
  • Hi.

    Hab mal etwas weiter gemacht. Ich habe es nun soweit raus, dass ich eine lokale Default-Konfiguration im Modul haben kann, die von außen geändert wird.

    Außerdem kann ich einen String von außen an das Modul übergeben, der geändert und zurückgegeben wird.

    Außerdem habe ich ein App Objekt mit dem Namen ao gemacht und das Hauptprogramm in eine Kapselfunktion gepackt.
    Ich habe keine Erfahrung mit OOP, deswegen habe ich auch ein bisschen mit privaten und öffentlichen Methoden experimentiert. Das gehört zwar nicht zur ursprünglichen Fragestellung, aber ich habs mal drin gelassen.

    LG

    JavaScript-Quellcode: app.js

    1. 'use strict';
    2. //Test App
    3. var ao ={}; //ao = AppObject Hauptprogramm
    4. (function () { //Scope erstellen
    5. // Eigene Module
    6. var mymod = require('./mymodule.js');
    7. // Config
    8. const ServerPort=8080;
    9. const ServerName="noname";
    10. console.log("Welcome!");
    11. //Allgemeines Konfigurationsobjekt erstellen
    12. var config={ value: "external-value"};
    13. mymod.showConfig(); // Konfiguration zeigen
    14. mymod.setConfig(config); // Externen Konfigurationswert setzen
    15. mymod.showConfig(); // Konfiguration zeigen
    16. var testdaten="Irgendwelche Testdaten";
    17. // Irgendwas an das Modul übergeben
    18. var result=mymod.doSomeStuff(testdaten);
    19. console.log(result);
    20. // Eine öffentliche Eigenschaft
    21. ao.testvalue_ext="foo";
    22. // eine private Eigenschaft
    23. var testvalue_int="bar";
    24. // Eine privilegierte öffentliche Methode
    25. ao.pub=function pub () {
    26. console.log("Ich bin von Außen zugreifbar");
    27. console.log(testvalue_int); // Kann auf interne Variablen zugreifen
    28. console.log(ao.testvalue_ext); // Kann auf öffentliche Eigenschaften zugreifen
    29. }
    30. // Eine private Methode
    31. var priv=function priv () {
    32. console.log("Ich bin NICHT von Außen zugreifbar");
    33. console.log(testvalue_int); // Kann auf interne Variablen zugreifen
    34. console.log(ao.testvalue_ext); // Kann auf öffentliche Eigenschaften zugreifen
    35. }
    36. priv();
    37. return ao;
    38. })();
    39. // Eine externe öffentliche Methode
    40. ao.ext=function ext () {
    41. console.log("Ich bin draussen");
    42. console.log(ao.testvalue_priv); // kann nicht auf private Eigenschaften zugreifen
    43. console.log(ao.testvalue_ext); //Aber auf öffentliche Eigenschaften
    44. }
    45. ao.pub();
    46. // ao.priv(); //Korrekterweise Fehlermeldung, Funktion ist privat
    47. ao.ext();
    Alles anzeigen


    Quellcode: mymodule.js

    1. 'use strict';
    2. // Testmodul
    3. // Konfigurationsobjekt erstellen und mit lokalen defaults befüllen
    4. var config={ value: "local-default-value" };
    5. // Konfigurationsobjekt durch externes Konfigurationsobjekt ändern
    6. function setConfig(obj) {
    7. config.value=obj.value;
    8. }
    9. // Anzeigen
    10. function showConfig() {
    11. console.log(config)
    12. }
    13. // Irgendwas machen
    14. function doSomeStuff(data) {
    15. data=data+ " Modifizierte Daten";
    16. return data;
    17. }
    18. // Exportieren
    19. exports.setConfig=setConfig;
    20. exports.showConfig=showConfig;
    21. exports.doSomeStuff=doSomeStuff;
    Alles anzeigen
  • Tobo schrieb:

    Im Hauptprogramm wird ein Konfigurationsobjekt aus einer JSON Datei eingelesen, das enthält z.B. den Server Namen.

    Die JSON-Datei wird in jeder Datei, die sie benötigt, mit einem eigenen require() eingebunden. Wie bereits erwähnt sind Module Singeltons. Die Datei würde also auch nur beim ersten Mal von der Festplatte ausgelesen werden.

    Tobo schrieb:

    Weitere Werte werden ebenfalls ermittelt und dem Objekt hinzugefügt. (z.B. __dirname)
    Sinnlos. __dirname steht als globale Variable sowieso überall zur Verfügung und für die meisten Anwendungen reichen auch relative Pfadangaben.


    Tobo schrieb:

    Und wie würde man eine Kommunikation zwischen Filereader und Webserver ermöglichen?
    Das Webserver-Modul importiert das Fileserver-Modul und verwendet dessen Funktionen.
  • Vielen Dank. Ich bin leider blutiger und bin mir über die Zusammenhänge noch nicht so ganz im Klaren.
    Ich habe nur ein bisschen Erfahrung aus PHP. Und dort auch nur mit Imperativer Programmierung, kein OOP.

    Wenn ich die Module überall dort, wo sie benötigt werden, ohne Nachteile nochmals einbinden kann, vereinfacht das natürlich die Sache enorm.
    Das spart dann natürlich das ganze "Hin und Her Geschiebe" von irgendwelchen Daten über Modulgrenzen hinweg.

    LG