Navigation

    Logo
    • Register
    • Login
    • Search
    • Recent
    • Tags
    • Unread
    • Categories
    • Unreplied
    • Popular
    • GitHub
    • Docu
    • Hilfe
    1. Home
    2. Deutsch
    3. Skripten / Logik
    4. JavaScript
    5. scriptedEnabled - Problem bei Abfrage

    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

    scriptedEnabled - Problem bei Abfrage

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

      @liv-in-sky sagte in scriptedEnabled - Problem bei Abfrage:

      muss ich lookForEnabled anders aufrufen

      Ja, hab ich doch geschrieben:

      @AlCalzone sagte in scriptedEnabled - Problem bei Abfrage:

      Und du musst das aus der aufrufenden Funktion ebenfalls mit await aufrufen, oder das Ergebnis mit .then(...) verarbeiten.

      z.B.

      async function whatever() {
      const result = await lookForEnabled("meine-id");
      log(result);
      }
      

      Ggf. empfiehlt sich die Lektüre von https://gist.github.com/AlCalzone/d14b854b69ce5e8a03718336cc650a95#

      1 Reply Last reply Reply Quote 0
      • paul53
        paul53 @liv-in-sky last edited by paul53

        @liv-in-sky sagte:

        muss ich die abfrage irgendwie anders programmieren ?

        Weshalb verwendest Du nicht die synchrone Funktion isScriptActive(name) ?

        function lookForEnabled(pfad) {
          pfad=pfad.replace(".js","")   
          pfad=pfad.replace(/\//g,".")  
          return isScriptActive(pfad);
        }
        
        liv-in-sky 1 Reply Last reply Reply Quote 0
        • liv-in-sky
          liv-in-sky @paul53 last edited by

          @paul53

          bin vor lauter frust in den regen raus und habe die blätter vom garten entsorgt - dieses await ... bekomme ich einfach nicht hin

          habe den link von @AlCalzone 20mal gelesen und das ganze script mit funktionen gemacht und wollte am ende eine .then kette machen

          die function kannte ich nicht - werd die sofort mal testen

          paul53 AlCalzone 2 Replies Last reply Reply Quote 0
          • paul53
            paul53 @liv-in-sky last edited by paul53

            @liv-in-sky sagte:

            die function kannte ich nicht

            Ich auch nicht: Ist erst seit 9. Oktober dokumentiert.

            1 Reply Last reply Reply Quote 0
            • AlCalzone
              AlCalzone Developer @liv-in-sky last edited by

              @liv-in-sky sagte in scriptedEnabled - Problem bei Abfrage:

              bin vor lauter frust in den regen raus und habe die blätter vom garten entsorgt - dieses await ... bekomme ich einfach nicht hin

              Auch wenn es eine einfachere Lösung gibt, vielleicht zeigst du mal was du hattest. So schwer ist es eigentlich nicht.
              Wenn ne Funktion einen Promise zurückgibt, rufst du sie mit await davor auf. Dazu muss die Funktion, in der await verwendet wird, async sein. Ansonsten wird der Code geschrieben wie synchroner Code.

              liv-in-sky 1 Reply Last reply Reply Quote 1
              • liv-in-sky
                liv-in-sky @AlCalzone last edited by liv-in-sky

                @AlCalzone

                erst mal danke für deine hilfe für dein angebot - darauf komme ich noch zurück - brauch jetzt erstmal eine pause
                bei der anderen version, hatte ich das problem, dass ich eine function hatte, in der ich mit await getStateAsync(id)).val das enabled suche - dann wollte ich aber, dass diese function ein ein promise bringt, wenn sie fertig ist und dann erst der datenpunkt geschrieben wird - ich konnte kein new promise einfügen, weil dann await getStateAsync(id)).val einen fehler anzeigte

                ung. so:

                 asyncfunction writeStuff() {
                return new Promise((resolve) => {......
                                               ....... await    lookForEnabled(pfad)                                        
                 resolve()
                

                hier kam ein fehler und await war nicht mehr erlaubt

                meine jetzige lösung sieht so aus (hoffe, die ist richtig):

                sammleDaten().then(writeStuff).then( function() { setState("javascript."+instance+".CheckScript.jsonSubScript",JSON.stringify(mxJson))
                                                               log(JSON.stringify(mxJson))})
                

                sammleDaten (liest scripte aus filesystem und versucht die trigger daraus zu finden - schreibt ein arr mit gefundenen non-existent datenpunkten) und writeStuff (checkt script_enabled und macht json für vis-datenpunkt )- beide functionen haben ein promise bekommen und ein resolve

                damit der datenpunkt zum richtigen zeitpunkt geschrieben wird

                @paul53 - die function hat das ganze extrem vereinfacht - nochmals danke dafür

                ergebnis schaut richtig aus:

                Image 8.png

                AlCalzone 1 Reply Last reply Reply Quote 0
                • AlCalzone
                  AlCalzone Developer @liv-in-sky last edited by AlCalzone

                  @liv-in-sky sagte in scriptedEnabled - Problem bei Abfrage:

                  async function writeStuff() {
                  return new Promise((resolve) => {......

                                              ....... await    lookForEnabled(pfad)                                        
                  

                  resolve()

                  Zwei Fehler hast du hier:

                  1. Eine async-Funktion braucht nicht explizit einen Promise zurückgeben. In 99% der Fälle ist es sogar einfach nur falsch. Das was ich oben sehe, kannst du wie folgt eindampfen:
                  async function writeStuff() {
                    // ...
                    await lookForEnabled(pfad);
                  }
                  
                  1. Wenn es unbedingt sein muss, await doch in einem Promise zu kapseln (z.B. weil du zusätzlich eine Callback-API nutzt), muss die Promise-"Callback"-Funktion als async definiert werden, nicht die außenrum:
                  function foobar() {
                    return new Promise(async (resolve) => {
                      await irgendwas;
                      irgendwasMitCallback(() => resolve());
                    });
                  });
                  

                  Meistens lässt sich das aber eleganter trennen.


                  meine jetzige lösung sieht so aus

                  Würde ich in etwa so machen (besser lesbar und mischt nicht async/await mit .then()-Ketten):

                  async function doStuff() {
                  	await sammleDaten();
                  	await writeStuff();
                  	// ^ Hier sollten vermutlich Daten zwischen den Methoden übergeben werden,
                  	// damit keine globalen Variablen missbraucht werden
                  	// const daten = await sammleDaten();
                  	// await writeStuff(daten)
                  	const stringified = JSON.stringify(mxJson);
                  	await setStateAsync("javascript."+instance+".CheckScript.jsonSubScript", stringified);
                  	log(stringified);
                  }
                  
                  liv-in-sky 3 Replies Last reply Reply Quote 0
                  • liv-in-sky
                    liv-in-sky @AlCalzone last edited by

                    @AlCalzone sagte in scriptedEnabled - Problem bei Abfrage:

                    Würde ich in etwa so machen (besser lesbar und mischt nicht async/await mit .then()-Ketten):
                    async function doStuff() { await sammleDaten(); await writeStuff(); // ^ Hier sollten vermutlich Daten zwischen den Methoden übergeben werden, // damit keine globalen Variablen missbraucht werden // const daten = await sammleDaten(); // await writeStuff(daten) const stringified = JSON.stringify(mxJson); await setStateAsync("javascript."+instance+".CheckScript.jsonSubScript", stringified); log(stringified); }

                    funktioniert - und leuchtet sogar mir ein 🙂

                    vielen dank für deine unterstützung

                    jetzt kann ich mich wieder auf das eigentliche script konzentrieren - das herausfiltern der trigger

                    1 Reply Last reply Reply Quote 1
                    • liv-in-sky
                      liv-in-sky @AlCalzone last edited by

                      @AlCalzone

                      es muss ich dich leider nochmal bemühen:

                      ich wollt auch einen datenpunkt anlegen und/oder beschreiben am anfang - habe es tatsächlich geschafft, den adapter zum neustart zu bringen

                      async function doStuff() {
                          // if (await !existsStateAsync("javascript."+instance+".CheckScript.jsonSubScript")) {
                          //     await createStateAsync("CheckScript.jsonSubScript", '[{"dp":"noch nicht da","enabled":"","script":""}]',
                          //                     {type: 'string', name: 'jsonSubScript', role: 'value', read: true , write: true} );}
                          await createStateAsync("CheckScript.jsonSubScript", '[{"dp":"noch nicht da","enabled":"","script":""}]',
                                                {type: 'string', name: 'jsonSubScript', role: 'value', read: true , write: true} );
                          await setStateAsync("javascript."+instance+".CheckScript.jsonSubScript",'[{"dp":"noch nicht da","enabled":"","script":""}]')  //}      
                      	await sammleDaten();
                      	await writeStuff();
                      	// ^ Hier sollten vermutlich Daten zwischen den Methoden übergeben werden,
                      	// damit keine globalen Variablen missbraucht werden
                      	// const daten = await sammleDaten();
                      	// await writeStuff(daten)
                          //await wait(5000);
                      	const stringified = JSON.stringify(mxJson);
                      	await setStateAsync("javascript."+instance+".CheckScript.jsonSubScript", stringified);
                      	log(stringified);
                      }
                      
                      doStuff()
                      
                      

                      diese version läuft einmal und beim 2ten mal, wenn der dp existiert, crasht der adapter.
                      die auskommentierte version war ein versuch vorher zu abzufragen - scheitert aber auch

                      1 Reply Last reply Reply Quote 0
                      • liv-in-sky
                        liv-in-sky @AlCalzone last edited by

                        @AlCalzone

                        so wird wenigstens der error abgefangen - gibt es da eine andere lösung?

                             try {
                            await createStateAsync("CheckScript.jsonSubScript", '[{"dp":"noch nicht da","enabled":"","script":""}]',
                                                  {type: 'string', name: 'jsonSubScript', role: 'value', read: true , write: true} );
                             } catch (error) {
                                log(`Unexpected error - ${error}`, 'error');
                            }
                            await setStateAsync("javascript."+instance+".CheckScript.jsonSubScript",'[{"dp":"noch nicht da","enabled":"","script":""}]')  //}      
                        	await sammleDaten();
                        	await writeStuff();
                        	// ^ Hier sollten vermutlich Daten zwischen den Methoden übergeben werden,
                        	// damit keine globalen Variablen missbraucht werden
                        	// const daten = await sammleDaten();
                        	// await writeStuff(daten)
                            //await wait(5000);
                        	const stringified = JSON.stringify(mxJson);
                        	await setStateAsync("javascript."+instance+".CheckScript.jsonSubScript", stringified);
                        	log(stringified);
                        }
                        
                        doStuff()
                        
                        
                        AlCalzone 1 Reply Last reply Reply Quote 0
                        • AlCalzone
                          AlCalzone Developer @liv-in-sky last edited by

                          @liv-in-sky Bin gerade am nachvollziehen. CreateState gibt etwas zurück, das als Fehler interpretiert wird, wenn der State existiert

                          liv-in-sky 1 Reply Last reply Reply Quote 0
                          • liv-in-sky
                            liv-in-sky @AlCalzone last edited by

                            @AlCalzone

                            ich dachte, dass könnte wie bei createState funktionieren - da wird auch einfach drübergegangen, wenn er existiert

                            AlCalzone 2 Replies Last reply Reply Quote 0
                            • AlCalzone
                              AlCalzone Developer @liv-in-sky last edited by AlCalzone

                              @liv-in-sky Das Problem liegt daran, dass alle ...Async Methoden intern die nicht-Async-Varianten nutzen. Das erste Argument der Callbacks wird als Fehler interpretiert. Das stimmt auch meistens, aber createState gibt sowohl bei Fehlern als auch bei existierenden States hier einen String zurück:

                              getState(..., (err) => {
                                  // Bei existierendem State: err === id
                                  // Bei Fehler: err === Fehlertext
                              });
                              

                              Das entspricht aber nicht der Konvention, dass bei Callbacks der erste Parameter der Fehler ist.

                              Dein Workaround war fast richtig - beachte die Klammern hinter ! im if:

                              if (!(await existsStateAsync("javascript." + instance + ".CheckScript.jsonSubScript"))) {
                                      await createStateAsync(
                                          "CheckScript.jsonSubScript",
                                          '[{"dp":"noch nicht da","enabled":"","script":""}]',
                                          {
                                              type: "string",
                                              name: "jsonSubScript",
                                              role: "value",
                                              read: true,
                                              write: true,
                                          }
                                      );
                                  }
                              
                              paul53 liv-in-sky 2 Replies Last reply Reply Quote 0
                              • paul53
                                paul53 @AlCalzone last edited by

                                @AlCalzone sagte:

                                if (!(await existsStateAsync("javascript." + instance + ".CheckScript.jsonSubScript"))) {

                                Sollte man es wirklich so machen, wenn ein synchrones existsState(id) existiert ?

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

                                  @paul53 Du musst nicht, aber das asynchrone vermeidet Probleme mit dem Cache

                                  paul53 1 Reply Last reply Reply Quote 0
                                  • AlCalzone
                                    AlCalzone Developer @liv-in-sky last edited by

                                    @liv-in-sky BTW, der Fix wird vermutlich ebenfalls in 4.9.5 enthalten sein:
                                    https://github.com/ioBroker/ioBroker.javascript/pull/692

                                    AlCalzone created this issue in ioBroker/ioBroker.javascript

                                    closed createState: pass ID as the result, not the error to the callback #692

                                    1 Reply Last reply Reply Quote 0
                                    • liv-in-sky
                                      liv-in-sky @AlCalzone last edited by

                                      @AlCalzone

                                      das bedeutet, wenn ich in einem script selbst datenpunkte anlege, muss ich am besten immer so vorgehen und scripte gleich so wie dieses hier aufbauen -try u. catch habe ich mit deinem beispiel ersetztu und läuft

                                      zusammengefaßt:
                                      lauter async funktionenen , die anschliessend in einer async. hauptfunktion mit await aufgerufen werden und am ende wird die hauptfunktion aufgerufen

                                      dann sollte man doch meist auf der sicheren seite sein

                                      wenn ich eine api abrufe muss ich auch noch deinen tipp von oben berücksichtigen

                                      function foobar() {
                                        return new Promise(async (resolve) => {
                                          await irgendwas;
                                          irgendwasMitCallback(() => resolve());
                                        });
                                      });
                                      
                                      AlCalzone 1 Reply Last reply Reply Quote 0
                                      • paul53
                                        paul53 @AlCalzone last edited by paul53

                                        @AlCalzone sagte:

                                        das asynchrone vermeidet Probleme mit dem Cache

                                        Da gebe ich Dir recht. Mit dem States-Puffer gab es schon manchmal Probleme.

                                        EDIT: Allerdings greift auch die asynchrone Version auf den Puffer zu:

                                                existsState:    function (id, callback) {
                                                    if (typeof callback === 'function') {
                                                        adapter.getForeignObject(id, (err, obj) =>
                                                            callback(err, obj && obj.type === 'state' && states.get(id) !== undefined));
                                        
                                        1 Reply Last reply Reply Quote 0
                                        • AlCalzone
                                          AlCalzone Developer @liv-in-sky last edited by

                                          @liv-in-sky sagte in scriptedEnabled - Problem bei Abfrage:

                                          lauter async funktionenen , die anschliessend in einer async. hauptfunktion mit await aufgerufen werden und am ende wird die hauptfunktion aufgerufen
                                          dann sollte man doch meist auf der sicheren seite sein

                                          In 4.9.x kannst du sogar die Haupt-Funktion weglassen. Top-Level-Await funktioniert da!

                                          // nix
                                          await irgendwas;
                                          // auch nix
                                          

                                          wenn ich eine api abrufe muss ich auch noch deinen tipp von oben berücksichtigen

                                          Dann aber bitte so:

                                          function asyncAPI() {
                                            return new Promise((resolve) => {
                                              irgendwasMitCallback(() => resolve());
                                            });
                                          });
                                          
                                          1 Reply Last reply Reply Quote 1
                                          • liv-in-sky
                                            liv-in-sky last edited by liv-in-sky

                                            nur nebenbei gefragt - ihr habt das problem nicht, dass die suche im scripte tab die browser zum crashen bringt ?

                                            https://github.com/ioBroker/ioBroker.javascript/issues/666

                                            ITCrowdIOB created this issue in ioBroker/ioBroker.javascript

                                            closed Suchfunktion blockiert den Browser. #666

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

                                            Support us

                                            ioBroker
                                            Community Adapters
                                            Donate

                                            874
                                            Online

                                            31.8k
                                            Users

                                            80.0k
                                            Topics

                                            1.3m
                                            Posts

                                            javascript
                                            4
                                            51
                                            2444
                                            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