Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. Asynchron bzw mir fehlt der Lösungsansatz

    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

    Asynchron bzw mir fehlt der Lösungsansatz

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

      ich habe folgendes Progrämmchen, welches mir die maximales Ventilöffnung von Heizkörperventilen eines Gewerkes ermitteln soll

      
      $('[state.id=*.VALVE_STATE](functions=Ventil_Anbau)').on (function (obj) {
          var MaxValve=-1;
          $('[state.id=*.VALVE_STATE](functions=Ventil_Anbau)').each (function (id, i) {
              getState (id, function (error,oID) {
                  if (oID.val>MaxValve) {
                      MaxValve= oID.val; 
                  }
                  log (oID.val + ", "+ MaxValve);
              });
          });
          log ("Maximal: " + MaxValve);
      });  
      

      sieht logisch aus, tuts aber leider nicht, da die $.each asychron läuft

      Der Aufruf tuts, aber wenn die Routine durchläuft, ergibt sich folgende Ausgabe

      Maximal: -1

      16, 16

      5, 16,

      32, 32

      8, 32

      Fragestellung:

      Wie kriege ichs hin, das Ausgabe von Maximal (später dann ein setState () ) das Schleifenergebnis ausgibt ?

      Danke für hilfreiche Ideen, Gruss und guten Rutsch, Black

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

        Disclaimer: Alles ungetestet!

        @Blackmike:

        Wie kriege ichs hin, das Ausgabe von Maximal (später dann ein setState () ) das Schleifenergebnis ausgibt ? `
        Die $-Funktion gibt ein Array zurück, das um ein paar Funktionen (on/each/…) erweitert wurde. Du kannst also vorher die Länge abfragen und dann beim letzten Eintrag die finale Logik ausführen:

        ! ````
        var valveIDs = $('state.id=*.VALVE_STATE');
        ! valveIDs.on(function (obj) {
        var MaxValve=-1;
        valveIDs.each(function (id, i) {
        getState(id, function (error,oID) {
        if (oID.val>MaxValve) {
        MaxValve = oID.val;
        }
        log(oID.val + ", "+ MaxValve);

                if (i === valveIDs.length - 1) {
                    log ("Maximal: " + MaxValve);
                    // Weiterer Code, der zum Abschluss der Prüfung ausgeführt wird
                }
            });
        });
        

        });

        ! ````
        Ich würde aber behaupten, dass nicht die .each-Funktion asynchron ausgeführt wird, sondern dass dein Problem daher kommt, dass du die asynchrone Variante von getState (mit Callback) verwendest. Einfacher geht es so:

        ! ````
        var valveIDs = $('state.id=*.VALVE_STATE');
        ! valveIDs.on(function (obj) {
        var MaxValve=-1;
        valveIDs.each(function (id, i) {
        // Hier liegt der Hase im Pfeffer:
        var curVal = getState(id);

            if (curVal > MaxValve) {
                MaxValve = curVal;
            }
            log(curVal + ", "+ MaxValve);       
        });
        
        log ("Maximal: " + MaxValve);
        // Weiterer Code, der zum Abschluss der Prüfung ausgeführt wird
        

        });

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

          ok, dann werde ich das mal angehen.

          ich habe alle getstates bei mir aber asynchron, ich habe 3 javascript adapter bei mir laufen, 1* produktiv, 1* device wrapper und 1* spiele und test adapter. der Unterschied bei load und CPU Temp mit haken bei "nicht alle Zustände bei Start abonieren" ist deutllich.

          von daher fände ich es nett, wenn es eine trickreichemöglichkeit gäbe, einen asychronen block irgendwie zu kapseln.

          ich werd deinen Ansatz mal testen, thnx erstmal, Black

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

            @Blackmike:

            ich habe alle getstates bei mir aber asynchron, `
            Dann solltest Du auch wissen, wie man damit umgeht. Für alle anderen gibt es die synchrone Version.

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

              @AlCalzone:

                          if (i === valveIDs.length - 1) {
                              log ("Maximal: " + MaxValve);
                              // Weiterer Code, der zum Abschluss der Prüfung ausgeführt wird
                          }
              ```` `  
              

              Das wird wahrscheinlich auch nicht funktionieren, da i schneller durchgezählt wird als die callbacks abgearbeitet sind.

              EDIT: So sollte es funktionieren:

              ! var valveIDs = $('[state.id=*.VALVE_STATE](functions=Ventil_Anbau)'); ! valveIDs.on(function (obj) { var MaxValve=-1; var j = 0; valveIDs.each(function (id, i) { getState(id, function (error,oID) { if (oID.val>MaxValve) { MaxValve = oID.val; } log(oID.val + ", "+ MaxValve); j++; if (j === valveIDs.length) { log ("Maximal: " + MaxValve); // Weiterer Code, der zum Abschluss der Prüfung ausgeführt wird } }); }); }); !

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

                @paul53:

                Das wird wahrscheinlich auch nicht funktionieren, da i schneller durchgezählt wird als die callbacks abgearbeitet sind. `
                Hast Recht. Dann bleibt noch außerhalb der each-Funktion eine Zählervariable zu definieren und diese bei jedem Callback-Aufruf zu erhöhen. Ist diese gleich der Array-Länge, sind wir fertig.

                @Blackmike:

                von daher fände ich es nett, wenn es eine trickreichemöglichkeit gäbe, einen asychronen block irgendwie zu kapseln. `
                Da deine asynchronen Funktionen alle auf eine gemeinsame Variable zugreifen, besteht eventuell die Gefahr einer race-condition. Das kannst du auf verschiedene Weisen umgehen.

                1. Indem du dir selbst eine "Funktionsschleife" baust:
                <list type="decimal">4. Statt .each auf dem ersten Array-Element getState aufrufen.

                1. Im Callback das erste Element aus dem Array entfernen.

                2. Ist das Array nun leer, bist du fertig. Sonst zurück zu 1.
                  Das Prinzip (ohne getState) wird z.B. im zwave-Adapter angewendet (funktion doFix) https://github.com/ioBroker/ioBroker.zw … in.js#L635

                Finde ich persönlich nicht so schön, da die eigentliche Aufgabe im Loop-Konstrukt verwaschen wird. Ich bevorzuge Promises:

                2. Mit Promises arbeiten

                Dazu musst du eine promisifizierte Version der getState-Funktion erstellen, nennen wir sie mal getStateP. Geht z.B. mit dieser Helfer-Funktion:

                (Ab NodeJS 6) https://github.com/AlCalzone/ioBroker.t … ises.js#L6

                (NodeJS 4) https://github.com/AlCalzone/ioBroker.g ... ises.js#L3

                const getStateP = promisify(getState);
                
                

                Dann erstellst du dir aus den State-IDs ein Array aus Promises

                const getStatePromises = valveIDs.map(id => getStateP(id));
                
                

                Darauf wartest du nun

                Promise.all(getStatePromises).then(results => {
                    // results ist ein Array mit den Werten deiner States
                    // Hier synchron weiterarbeiten
                    const MaxValve = Math.max(results); // kein Einzelvergleich nötig!
                    // Irgendwas mit dem Ergebnis machen
                }).catch(e => {
                    // Fehler behandeln
                });
                
                
                1 Reply Last reply Reply Quote 0
                • Blackmike
                  Blackmike last edited by

                  thnx, wieder einiges gelernt…

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

                  Support us

                  ioBroker
                  Community Adapters
                  Donate

                  771
                  Online

                  31.7k
                  Users

                  79.8k
                  Topics

                  1.3m
                  Posts

                  3
                  7
                  579
                  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