NEWS
scriptedEnabled - Problem bei Abfrage
-
@AlCalzone sagte:
if (!(await existsStateAsync("javascript." + instance + ".CheckScript.jsonSubScript"))) {
Sollte man es wirklich so machen, wenn ein synchrones existsState(id) existiert ?
-
@paul53 Du musst nicht, aber das asynchrone vermeidet Probleme mit dem Cache
-
@liv-in-sky BTW, der Fix wird vermutlich ebenfalls in 4.9.5 enthalten sein:
https://github.com/ioBroker/ioBroker.javascript/pull/692 -
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 aufgerufendann 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 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));
-
@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 seinIn 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()); }); });
-
nur nebenbei gefragt - ihr habt das problem nicht, dass die suche im scripte tab die browser zum crashen bringt ?
-
@liv-in-sky Nö
-
-
hi - ich schon wieder - brauche nochmal deinen sachverstand
habe jetzt den fall mit den api abfragen - zwei hintereinander - zuerst radarstelle finden - dann adresse anzeigen - (später dazu: an handy senden)
ist der code ok - außer die übergabe der werte an die nächste function
werte kommen richtig raus !
const BASE_URL="https://cdn2.atudo.net/api/1.0/vl.php?type=0,1,2,3,4,5,6&box=" const LATITUDE_START="48.312969" const LONGITUDE_START="11.701666" const LATITUDE_DEST="48.308288" const LONGITUDE_DEST="11.720184" const APIKEY_GEOCODING="4ddxxxxxxxx910f5a7b493d192e" var myLat="xx"; var myLng="yy"; var myRes="myRes"; async function getContent(){ return new Promise(async (resolve) => { var url = BASE_URL + LATITUDE_START + "," + LONGITUDE_START + "," + LATITUDE_DEST + "," + LONGITUDE_DEST request(url, function(err, response, json) { log(json) var myjson = JSON.parse(json).pois; log(myjson[0].lat+myjson[0].lng) myLat=myjson[0].lat myLng=myjson[0].lng resolve() }); }); } async function getAddress(lat, long){ return new Promise(async (resolve) => { var geoCodeUrl = 'https://api.opencagedata.com/geocode/v1/json' geoCodeUrl = geoCodeUrl + '?' + 'key=' + APIKEY_GEOCODING + '&q=' + lat + ',' + long + '&pretty=1' log(geoCodeUrl) request(geoCodeUrl, function(err, response, json) { //log("d--------"+json) log (JSON.parse(json).results[0].formatted); myRes=JSON.parse(json).results[0].formatted resolve() }); }); } async function doStuff(){ await getContent() //await getAddress("48.310381","11.706523") log(myLat) log(myLng) await getAddress(myLat,myLng) log(myRes) }
-
@liv-in-sky Ein paar Dinge:
-
Wenn du direkt in der Funktion kein
await
nutzt, brauchst du diese nicht alsasync
definieren, betrifft getContent, getAddress und den Promise-Executor -
Die Art die Werte zu übergeben (mit externen Variablen) ist etwas komisch. Üblicherweise würde man das "Ergebnis" einer Funktion per
return
zurück geben (oder im Falle von Promises anresolve
übergeben) -
Ich empfehle, komplett auf
let
(für veränderliche Variablen) undconst
(für Konstanten, bzw. nur 1x beschriebene Variablenstatt
var` zu setzen. Diese sind jeweils nur im enthaltenen Block definiert was einige schwer zu findende Bugs vermeidet. --> https://hackernoon.com/js-var-let-or-const-67e51dbb716f -
Ist Geschmackssache, aber in JavaScript verwendet man eigentlich Semikolons am Ende der Zeile. Man kann sie in vielen Fällen weglassen, sollte dann aber sehr genau wissen, wo man sie doch braucht.
-
würde ich dir
axios
stattrequest
ans Herz legen. Das arbeitet von Haus aus schon mit Promises: https://github.com/axios/axios
Habe dir die Vorschläge 1-3 mal hier umgesetzt:
const BASE_URL = "https://cdn2.atudo.net/api/1.0/vl.php?type=0,1,2,3,4,5,6&box=" const LATITUDE_START = "48.312969" const LONGITUDE_START = "11.701666" const LATITUDE_DEST = "48.308288" const LONGITUDE_DEST = "11.720184" const APIKEY_GEOCODING = "4ddxxxxxxxx910f5a7b493d192e" function getContent() { // kein async! return new Promise((resolve) => { // kein async! const url = BASE_URL + LATITUDE_START + "," + LONGITUDE_START + "," + LATITUDE_DEST + "," + LONGITUDE_DEST request(url, function (err, response, json) { log(json) const myjson = JSON.parse(json).pois; log(myjson[0].lat + myjson[0].lng) resolve({ // Rückgabe eines Objektes, muss wieder auseinander gepflückt werden lat: myjson[0].lat, lng: myjson[0].lng }); }); }); } function getAddress(lat, long) { // kein async! return new Promise((resolve) => { // kein async! let geoCodeUrl = 'https://api.opencagedata.com/geocode/v1/json' geoCodeUrl = geoCodeUrl + '?' + 'key=' + APIKEY_GEOCODING + '&q=' + lat + ',' + long + '&pretty=1' log(geoCodeUrl) request(geoCodeUrl, function (err, response, json) { //log("d--------"+json) log(JSON.parse(json).results[0].formatted); const myRes = JSON.parse(json).results[0].formatted; // Direkte Rückgabe des Wertes: resolve(myRes) }); }); } async function doStuff() { // ^ hier brauchst du wirklich async, weil du im nächsten Befehl await nutzt! // Rückgabewert in lat und lng auseinander dividieren: const {lat, lng} = await getContent(); //await getAddress("48.310381","11.706523") log(lat) log(lng) const myRes = await getAddress(lat, lng); log(myRes) }
Weiterhin solltest du bei jedem Request prüfen, ob die Anfrage erfolgreich war (mit dem err-Parameter). Weil nur dann ist
json
auch definiert. Wenns mal nicht klappt, stürzt sonst dein Skript ab! -
-
@AlCalzone woow, puuh und tausend dank
habe jetzt umgebaut - können auch mehrere blitzer zurückkommen!
- axios muss ich näher ansehen - stand schon auf liste
- strichpunkte - vergeß ich immer
- wann merk ich mir das mit let eigentlich
- fehler sollten auch abgefangen werden
const BASE_URL="https://cdn2.atudo.net/api/1.0/vl.php?type=0,1,2,3,4,5,6&box=" const LATITUDE_START="45.618674"//"48.605395"//"45.618674"//"48.618674" "48.605395"// const LONGITUDE_START="11.813714"//"11.847123"//"11.813714" "11.847123"// const LATITUDE_DEST="48.607892" const LONGITUDE_DEST="11.840321" const APIKEY_GEOCODING="4ddxxxxxxxxxx0f5a7b493d192e" let myRes=[]; function getContent() { // kein async! return new Promise((resolve) => { // kein async! const url = BASE_URL + LATITUDE_START + "," + LONGITUDE_START + "," + LATITUDE_DEST + "," + LONGITUDE_DEST request(url, function (err, response, json) { //log(json.length);log(err) // let myjson=Testing2 // log("get die Blitzer "+myjson.pois[0].lat) if(json.length>25 && err==null) {log("hat key") // if(json.length>25 && err==null) {log("hat key") const myjson = JSON.parse(json).pois; let myBlitzRes=[]; for(let i=0;i<myjson.length;i++){ // for(let i=0;i<myjson.pois.length;i++){ myBlitzRes.push({ lat: myjson[0].lat, lng: myjson[0].lng // lat: myjson.pois[0].lat, // lng: myjson.pois[0].lng }); resolve(myBlitzRes)} } else{resolve(["empty"])} }); }); } function getAddress(lat, long) { // kein async! return new Promise((resolve) => { // kein async! let geoCodeUrl = 'https://api.opencagedata.com/geocode/v1/json' geoCodeUrl = geoCodeUrl + '?' + 'key=' + APIKEY_GEOCODING + '&q=' + lat + ',' + long + '&pretty=1' // log(geoCodeUrl) request(geoCodeUrl, function (err, response, json) { // log(JSON.parse(json).results[0].formatted); if (err==null){ const myRes = JSON.parse(json).results[0].formatted; // Direkte Rückgabe des Wertes: resolve(myRes)} else {resolve("keine Adress-Auflösung möglich")} }); }); } async function doStuff() { const myBlitzer = await getContent(); log("meine blitzer "+JSON.stringify(myBlitzer)) //await getAddress("48.310381","11.706523") if(myBlitzer[0]!="empty") { // log(myBlitzer[0].lat); log(myBlitzer[0].lng) for(let i=0;i<myBlitzer.length;i++){ await getAddress(myBlitzer[i].lat, myBlitzer[i].lng); myRes.push(await getAddress(myBlitzer[i].lat, myBlitzer[i].lng)) } //log(myRes.toString()) log( myRes.toString()) } else {log("KEINE BLITZER !!!!!")} } doStuff(); const Testing= {"pois":[{"id":"8073768268","lat":"47.854144","lat_s":"47.9","lng":"11.803649","lng_s":"11.8","street":"Miesbacher Stra\u00dfe","content":"6291143405","backend":"0-14134538","type":"1","vmax":"50","counter":"3","create_date":"2020-10-29 12:29:51","confirm_date":"2020-10-29 13:08:03","gps_status":"-","info":"{\"count_180d\":\"5\"}","polyline":""},{"id":"8073768176","lat":"50.863275","lat_s":"50.9","lng":"11.850087","lng_s":"11.9","street":"L107","content":"6291097692","backend":"0-14134432","type":"1","vmax":"70","counter":"2","create_date":"2020-10-29 12:08:50","confirm_date":"2020-10-29 13:22:08","gps_status":"-","info":"{\"count_180d\":\"0\"}","polyline":""},{"id":"8073768112","lat":"48.611621","lat_s":"48.6","lng":"11.824882","lng_s":"11.8","street":"St 2049","content":"6291067255","backend":"0-14134349","type":"1","vmax":"50","counter":"3","create_date":"2020-10-29 11:55:24","confirm_date":"2020-10-29 13:21:00","gps_status":"-","info":"{\"count_180d\":\"0\"}","polyline":""},{"id":"8073767869","lat":"47.946894","lat_s":"47.9","lng":"11.791351","lng_s":"11.8","street":"St 2078","content":"6290927668","backend":"0-14134006","type":"1","vmax":"50","counter":"3","create_date":"2020-10-29 10:54:12","confirm_date":"2020-10-29 13:26:21","gps_status":"-","info":"{\"count_180d\":\"0\"}","polyline":""}],"grid":[]} const Testing2= {"pois":[],"grid":[]}
-
@liv-in-sky sagte in scriptedEnabled - Problem bei Abfrage:
json.length>25 && err==null
Wenn
err
nicht null ist, dann istjson
nicht unbedingt definiert. Die Reihenfolge müsste anders herum sein.else {resolve("keine Adress-Auflösung möglich")}
Das was du da vor hast (Fehler übergeben), geht besser mit
reject
. Prinzipiell:function doSomething() { return new Promise((resolve, reject) => { // ... irgendwas tun, bei Fehler: reject("Etwas ist schief gelaufen"); }); } async function stuff() { try { await doSomething(); } catch (e) { // Hier landest du, wenn oben `reject` aufgerufen wird } }