Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Entwicklung
    4. [Frage] Wie ist der richtiger Umgang mit Callbacks?

    NEWS

    • Monatsrückblick - April 2025

    • Minor js-controller 7.0.7 Update in latest repo

    • Save The Date: ioBroker@Smart Living Forum Solingen, 14.06.

    [Frage] Wie ist der richtiger Umgang mit Callbacks?

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

      Hallo zusammen,

      ich arbeite nach wie vor an meiner ioBroker.homehub Visualisierung. Ich kann die Konfiguration der Instanz einlesen und States anzeigen.

      Jetzt möchte ich noch die Objekte einlesen. Das Ganze soll in folgender Reihenfolge passieren: Erst die Konfiguration der Instanz, dann die Objekte und dann die States. Irgendwie kriege ich das mit den Callbacks aber nicht auf die Reihe.

      Hier mal der Code, den ich momentan habe:

      function initializeHomehub(){
          console.log('Initializing HomeHub');
      
          // Reset everything
          config['initiated'] = false;
          config['categories'] = [];
          config['objects'] = [];
          config['states'] = [];
      
          // Use callbacks to first fetch configuration then objects and then states
          fetchStates(
              fetchObjects(
                  fetchConfiguration()
              )
          );
      }
      
      function fetchConfiguration(callback) {
          callback = (typeof callback === 'function') ? callback : function() {};
      
          console.log('Fetching configuration');
      
          servConn.getObject('system.adapter.homehub.0', false, function (error, obj) {
              console.log('Received configuration.');
      
              config['categories'] = obj['native']['categories'];
      
              callback;
          });
      }
      
      function fetchObjects(callback) {
          callback = (typeof callback === 'function') ? callback : function() {};
      
          console.log('Fetching objects');
      
          servConn.getObjects(function (err, _objects) {
              console.log('Received objects.');
      
              config['objects'] = _objects;
      
              callback;
          });
      }
      
      function fetchStates(callback) {
          callback = (typeof callback === 'function') ? callback : function() {};
      
          console.log('Fetching states');
      
          servConn.getStates(function (err, _states) {
              console.log('Received states.');
      
              config['states'] = _states;
      
              config.initiated = true;
      
              callback;
          });
      }
      

      Die Funktion initializeHomehub() soll einmal aufgerufen werden und dann die anderen Funktionen aufrufen. Die Ergebnisse sollen jeweils in die Variable config geschrieben werden.

      Die Ergebnisse werden in die config Variable geschrieben, aber in der Reihenfolge Konfiguration, States, Objects.

      Hat jemand einen Tipp für mich?

      Gruß,
      Markus

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

        wenn du den callback aufrufst, müsste das dann nicht

        callback();
        

        heißen, anstatt einfach nur

        callback;
        
        1 Reply Last reply Reply Quote 0
        • T
          tim3trick last edited by

          Zuerst das was @OliverW sagt, wenn der callback ausgeführt werden soll, musst du das auch mit

          callback(); //Klammern!
          

          machen.

          Dann darfst du im Teil

              fetchStates(
                  fetchObjects(
                      fetchConfiguration()
                  )
              );
          

          Nicht die "aufgerufenen Funktionen" d.h. ihre Ergebnisse übergeben, sondern lediglich die Referenz auf die Funktion:

          // rufe die fetchObjects Funktion auf und übergebe ihr die Funktion fetchConfiguration als Callback
            fetchObjects(
              fetchConfiguration
            )
          

          Deine Dreier-Kette würde dann so aussehen:

              fetchStates(fetchObjects.bind(null, fetchConfiguration));
          

          Hier wird zuerst eine "virtuelle Methode" erstellt, die das gleiche tut wie fetchObjects, mit dem scope=null und dem vorausgefüllten Parameter callback = fetchConfiguration (das ist fachlich falsch, aber als Erklärung in Ordnung, denke ich).
          Diese "virtuelle Methode" wird als Callback der fetchStates Funktion übergeben.
          Jetzt wird zuerst fetchStates ausgeführt, (wenn du den oben genannten Fix gemacht hast) die auf fetchObjects "virtuelle Methode" und dann im Anschluss fetchConfiguration.

          Nichtsdestotrotz rate ich dir aber, entweder mit Promises oder direkt async / await zu arbeiten, die machen dir das Leben viel leichter.
          Änderst du deine Methoden wie folgt ab:

          function fetchConfiguration(callback) {
              console.log('Fetching configuration');
              return new Promise((resolve, reject) => {
                servConn.getObject('system.adapter.homehub.0', false, function (error, obj) {
                    if (error) {
                      return reject(error);
                    }
                    console.log('Received configuration.');
                    config['categories'] = obj['native']['categories'];
                    resolve();
                });
              });
          }
          function fetchObjects(callback) {
              return new Promise((resolve, reject) => {
                console.log('Fetching objects');
                servConn.getObjects(function (err, _objects) {
                  	if (err) {
                      return reject(err);
                    }
                    console.log('Received objects.');
                    config['objects'] = _objects;
                    resolve();
                });
              });
          }
          function fetchStates(callback) {
              return new Promise((resolve, reject) => {
                console.log('Fetching states');
                servConn.getStates(function (err, _states) {
                    if (err) {
                      return reject(err);
                    }
                    console.log('Received states.');
                    config['states'] = _states;
                    config.initiated = true;
                    resolve();
                });
              });
          }
          

          kannst du sie so zusammen setzen:

          fetchStates()
            .then(fetchObjects)
            .then(fetchConfiguration)
            .then(() => { console.log("Done") }) //or something useful
            .catch(console.error) //or something useful
          

          bzw.

          //für await ist noch etwas vorarbeit erforderlich, aber die spare ich hier und heute aus
          await fetchStates();
          await fetchObjects();
          await fetchConfiguration();
          

          was alles viel viel lesbarer ist (und dir die Callback Hell erspart)

          AlCalzone 1 Reply Last reply Reply Quote 0
          • AlCalzone
            AlCalzone Developer @tim3trick last edited by

            @tim3trick sagte in [Frage] Wie ist der richtiger Umgang mit Callbacks?:

            fetchStates(fetchObjects.bind(null, fetchConfiguration));

            Hier wird zuerst eine "virtuelle Methode" erstellt, die das gleiche tut wie fetchObjects, mit dem scope=null und dem vorausgefüllten Parameter callback = fetchConfiguration (das ist fachlich falsch, aber als Erklärung in Ordnung, denke ich).

            Das funktioniert zwar, lesbarer und verständlicher ist IMO aber folgende Variante:

            fetchStates(
                () => fetchObjects(
                    () => fetchConfiguration()
                )
            );
            

            Die ist außerdem näher dran an dem, was @braindead zuerst hatte (nur dass er die Funktionen direkt aufgerufen hat, statt Callbacks zu definieren.

            1 Reply Last reply Reply Quote 0
            • braindead
              braindead Developer last edited by

              Vielen Dank für Eure Hilfe. Kaum mache ich es richtig, funktioniert es genauso, wie es sein soll. 🙂

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

              Support us

              ioBroker
              Community Adapters
              Donate

              895
              Online

              31.6k
              Users

              79.4k
              Topics

              1.3m
              Posts

              4
              5
              745
              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