Helgor: Wie Variable als Argument einer Funktion übergeben?

Hallo, ich versuche gerade, eine rekursive Funktion (hier rinseNrepeat) zu schreiben, die ich möglichst allgemein halten will, damit ich sie mehrmals flexibel einsetzen kann (und so unnötige Redundanzen vermeide).

Diese Funktion beinhaltet nun leider ein setTimeout, welches von außerhalb der Funktion wieder gecleared werden soll, hier exemplarisch auf button click. Dazu muss ich das Timeout in einer von außerhalb des Funktionsscope zugänglichen Variable speichern (damit der Button Zugriff hat).

Wenn ich die setTimeout-Variable aber innerhalb der Funktion hardcode, so ist diese nicht mehr flexibel gehalten und allgemein überall verwendbar, daher wollte ich die Variable, in der das setTimeout gespeichert wird, als Argument der Funktion übergeben. Dazu definiere ich zuerst ein Objekt (hier: varSammelobjekt). In diesem Objekt will ich nun die Timeouts speichern, nach dem Schema

varSammelobjekt = {
	Timeout1: setTimeout(rinseNrepeat, 1000),
	// etc.
};

Das funktioniert leider nicht so, wie ich mir das vorstelle. Was mache ich falsch, wie mache ich's richtig?

Der Kot:

const stopDenWahnsinn = document.getElementById("stopDenWahnsinn"); // im DOM ein Button mit dieser ID
let varSammelobjekt = {};

function rinseNrepeat(timeoutVar) {
	console.log("Hallo aus Funktion");
	// Weiterer Code
	timeoutVar = setTimeout(rinseNrepeat, 1000);
}
rinseNrepeat(varSammelobjekt["Timeout1"]);

stopDenWahnsinn.addEventListener("click", () => {
	clearTimeout(varSammelobjekt["Timeout1"]);
	// tut nix X(
});

Dank euch mit Herzlichkeit

  1. Hallo,

    hab das Debakel doch selbst gelöst...

    Des Pudels Kern: natürlich kennt die rinseNrepeat Funktion die Parameter nicht mehr, wenn das Timeout sie ohne Parameter aufruft 🤦‍♂️

    Dank trotzdem

  2. Hallo Helgor,

    nein, so macht man das nicht. Das Sammelobjekt ist ja auch wieder global. Damit verlagerst Du nur das Problem von der Timeout-Variablen auf das Sammelobjekt.

    Die Idee ist, eine Closure zu benutzen (Erklärungen im SelfWiki).

    Und eigentlich möchtest Du doch setInterval verwenden, um setTimeout nicht immer wieder neu aufrufen zu müssen, oder?

    function runRinseNRepeat(stopButton) {
       const intervalTimer = setInterval(rubRubDubDub, 1000);
    
       stopButton.addEventListener("click", 
          () => {
             console.log("Clean!!!");
             clearInterval(intervalTimer);
       });
    
       function rubRubDubDub() {
          console.log("With a rub rub rub and a dub dub dub in the water in the water...");
          // do Work
       }
    }
    
    // somewhere else
    runRinseNRepeat(document.getElementById("stopDenWahnsinn"));
    

    Die vom Click-Handler und von rubRubDubDub gebildeten Closures teilen sich den Scope von runRinseNRepeat und können damit auch nach Ende dieses Funktionsaufrufs darauf zugreifen.

    Je nachdem, wie dein übriger Code aussieht, reicht das hin. Aber wenn runRinseNRepeat nun eine globale Funktion ist, dann ist das Problem, den globalen Fußabdruck zu vermeiden, immer noch nicht gelöst. Das geht aber, und zwar, wenn Du runRinseNRepeat zu einer IIFE machst:

    (function(stopButton) {
      const intervalTimer = setInterval(rubRubDubDub, 1000);
    
      stopButton.addEventListener("click", () => {
          console.log("Clean!!!");
          clearInterval(intervalTimer);
        });
    
      function rubRubDubDub() {
        console.log("With a rub rub rub and a dub dub dub in the water in the water...");
        // do Work
      }
    })(document.getElememtById("stopDenWahnsinn"));
    

    Ob Du document.getElememtById("stopDenWahnsinn") nun als Parameter in die IIFE hineingibst oder es drinnen direkt einbaust, ist Geschmackssache oder mag auch an anderen Rahmenbedingungen hängen. Du kannst auch nur die ID hineingeben.

    Natürlich kannst Du das, wenn Du es unbedingt willst, auch mit setTimeout lösen. In rubRubDubDub ist die intervalTimer-Variable genauso verfügbar. Du musst dann nur let statt const verwenden...

    Rolf

    --
    sumpsi - posui - obstruxi