Jan Kuchař
17.5.2024 v 10:56
Dobrý den,
proti zneužití je potřeba API klič zabezpečit
Obvykle se to řeší tak že si vytvoříte dva API klíče (je možno jakékoliv množství klíčů v rámci jednoho projektu) a jeden který budete mít na webu zabezpečíte pro konkrétní URL
Druhý nezabezpečený budete používat lokálně na PC při programování a testování
API klíč se zadává při volání každé funkce REST API i při načítání mapových dlaždic
na konkrétní kod se můžete podívat v ukázkách k jednotlivým funkcím
https://developer.mapy.cz/rest-api/funkce/
Jednotlivé funkce lze volat i bez zobrazení mapy
co se týká vámi vámi zmiňovaných výškových dat je při volání nutné dodržet omezení a to max 256 souřadnic pro jeden dotaz a max rozsah souřadnic 1x1 stupeň
Jan Horinek
17.5.2024 v 11:25
Díky, jak tedy JavaScript pozná, že volám API na mapy.cz?
Jan Kuchař
reagoval na příspěvek
od Jan Horinek
17.5.2024 v 11:35
pozná to z URL přes kterou je funkce volána
https://api.mapy.cz/v1/elevation?lang=cs&positions=${lon}%2C${lat}&apikey=${API_KEY}
Jan Horinek
17.5.2024 v 11:40
Aha, jasně, díky. Ten loader.js, který jsem zmiňoval prve právě zajišťoval přidání URL mapy.cz. Teď to dává smysl.
https://technologyadvice.com/blog/information-technology/how-to-use-an-api/
Jan Buriánek
17.5.2024 v 12:57
A já vám k tomu ještě poradím, jak správně vložit řadu až 256ti souřadnic do poptávky, protože tam to musí být správně vložené, jednotlivé souřadnice oddělené středníkem a mezi LAT LON hodnotou čárka, tečka je desetinná tečka.
např. takto:
let sou=""; for(let a of body){sou+=sou==""?"":";"; sou+=a.lng+","+a.lat}
tento kód má na začátku smyčky v proměnné sou prázdné uvozovky, takže nic nepřiřadí a vloží první LON - LAT souřadnice (pozor na pořadí LON-LAT!), a pro každý další bod přidá před něj středník. Tím se zajistí, že není středník na konci řetězce souřadnic. (sou je zkratka souřadnice... :)
no a pak to poptáte třeba takto
fetch('https://api.mapy.cz/v1/elevation?positions='+sou+'&apikey='+"API_KEY")
.then( .... atd
Jan Horinek
17.5.2024 v 15:33
Bezva, díky moc, už to funguje.
Jan Horinek
23.5.2024 v 22:03
Ještě dotaz.
Mám funkci
function ZavolejAPI(souradnice, pocet)
{
let apiUrl = 'https://api.mapy.cz/v1/elevation?lang=cs&positions=' + souradnice + '&apikey=' + API_KEY;
let vysky = [];
let vyska = 0;
fetch(apiUrl)
.then(response => response.json())
.then(data => {
for(let i = 0; i < pocet; i++)
{
vysky.push(data.items[i].elevation);
}
})
.catch(error => console.error('Chyba při volání API: ', error));
}
a volám jí
nadm_vyska_paty = ZavolejAPI(lng_end + ',' + lat_end, 1);
Kam do funkce mám umístit return aby vrátil hodnotu vyska = data.items[0].elevation ?
Neboli jedinou hodnotu pole data.items.
Jan Buriánek
reagoval na příspěvek
od Jan Horinek
23.5.2024 v 22:55
To je otázka, jak dalece si rozumíte s asynchronními funkcemi.
Funkce ZavolejAPI() proběhne celá, ale odloží všechny kódy za oběma .then na pozdější asynchronní zpracování, a nemůže vrátit žádný výsledek, protože ho ještě nezná, jen ho poptá.
Váš program pokračuje tam, odkud jste ZavolejAPI() zavolal. Ale žádné return nemůže vrátit hodnotu.
Na základě poptávky fetch() prohlížeč asynchronně (tedy bez toho, aby na to měl váš script nějaký vliv) pošle požadavek na server a bude čekat na jeho vrácení. Jakmile server pošle zpět hodnoty, sama se spustí funkce za prvním .then, tedy .json zpracování návratu, to je taky asynchronní. Jakmile je to dokončeno, sama se spustí funkce za dalším .then, tedy .then(data ... ) a ta se celá provede.
Ve smyčce tam máte uložení návratových hodnot z data do vaší proměnné vysky[].
Problém je v tom, že tuto proměnnou definujete let uvnitř funkce ZavolejAPI(), no a tím pádem proměnná existuje pouze uvnitř této funkce.
Čili i když se to spustilo samo dodatečně asynchronně, tak tu proměnnou to zná a data má kam uložit, nebude to vracet chybu.
Jenže jakmile to dokončí, proměnná i s hodnotami se definitivně ztratí.
Dalším voláním funkce ZavolejAPI() se to opakuje, proměnná let vysky=[] se definuje znovu, opět jen uvnitř funkce ZavolejAPI().
Stejně se zde ale bude chovat i var vysky=[]
Musíte buď nepoužít let nebo var, jen vysky=[], pak bude proměnná globální a hodnoty v ní zůstanou.
A dalším voláním se přepíšou na nové (samozřejmě až po asynchronním návratu)
Lepší je ale definovat proměnnou mimo funkci, před funkcí
Hodnoty se pak budou do proměnné výšky jen stále přidávat.
To samé platí i pro let vyska.
V následující ukázce (úpravě vašeho kódu) ani nepoužiju let vyska=0, ale po návratu dat se sama spustí funkce vykonejNeco(), jíž jako parametr předáme tu jednu první výšku.
let vysky = [];
//let vyska = 0;
function ZavolejAPI(souradnice, pocet){
let apiUrl = 'https://api.mapy.cz/v1/elevation?lang=cs&positions=' + souradnice + '&apikey=' + API_KEY;
fetch(apiUrl)
.then(response => response.json())
.then(data => {
for(let i = 0; i < pocet; i++){vysky.push(data.items[i].elevation);}
// vyska=data.items[0].elevation
vykonejNeco(data.items[0].elevation)
})
.catch(error => console.error('Chyba při volání API: ', error));
}
function vykonejNeco(vyska){console.log(vyska)}
(psal jsem to od ruky z paměti zde přímo v okně fóra, můžou tam být chyby)
Jan Buriánek
23.5.2024 v 23:12
Ještě doplním, že pokud byste chtěl, aby nadřazená funkce se zastavila a počkala na vrácení hodnoty, pak musí být nadřazená funkce asynchronní, v ní definovaná proměnná, do níž se uloží promise požadavek a na ten se pomocí await počká. Návrat pak v promise obsahuje i vrácené hodnoty, čili je to podobné return, jen se na to musí počkat.
...není to úplně jednoduché
Zkuste si prostudovat poslední funkci: async function main() {...} v ukázce čtení elevace zde:
https://developer.mapy.cz/rest-api/tutorialy/zobrazeni-vyskoveho-profilu-trasy/
Tam je to použito.
Jan Horinek
24.5.2024 v 11:29
Bezva, moc Vám děkuji za trpělivost a excelentní vysvětlení!
Jan Buriánek
reagoval na příspěvek
od Jan Horinek
24.5.2024 v 11:34
👍
Jan Horinek
24.5.2024 v 14:35
Ještě bych si dovolil Vás potrápit. Sestavil jsem to takto
let nadm_vyska_paty = 0;
nadm_vyska_paty = getElevation(lng_end + ',' + lat_end)
async function getElevation(souradnice)
{
const apiUrl = 'https://api.mapy.cz/v1/elevation?lang=cs&positions=' + souradnice + '&apikey=' + API_KEY;
const response = await fetch(apiUrl);
const data = await response.json();
return data.items[0].elevation;
}
Do proměnné nadm_vyska_paty se však neukládá hodnota, ale Promise, který má state a value.
Je nějaká metoda, jak do globální proměnné uložit value z Promise tak, aby to tam zůstalo a dalo se s tou proměnnou pracovat běžným způsobem?
Jan Kuchař
reagoval na příspěvek
od Jan Horinek
24.5.2024 v 15:07
Dobrý den,
funkce se zdá být už OK (podobně to mám také)
ale funkci bych volal takto:
getElevation(lng_end + ',' + lat_end).then( function(value) {
nadm_vyska_paty=value
// a zde další váš kod třeba
alert(nadm_vyska_paty)
})
protože pracovat s navrácenou hodnotou můžete teprve až jí vrátí
Jan Horinek
24.5.2024 v 15:27
Dík, možná, že chci něco neuskutečnitelného, ale
let nadm_vyska_paty=0;
getElevation(lng_end + ',' + lat_end).then( function(value) {
nadm_vyska_paty=value
console.log(nadm_vyska_paty);
})
console.log(nadm_vyska_paty);
vrátí v konzoli
0
470
protože to volání mimo metodu .then() se provede jako první a kód mimo ni bude brát nadm_vyska_paty jako 0, protože se provede celý jako první.
Lze tu načtenou hodnotu nějak vyvést ven mimo .then()?
Já jsem se právě domníval, že await udělá přesně tohle ...
Jan Horinek
24.5.2024 v 17:02
Už to chápu, tomu volání pokaždé když potřebuji hodnotu se nevyhnu. Nevadí, dík za pomoc.
Jan Kuchař
reagoval na příspěvek
od Jan Horinek
24.5.2024 v 18:40
No volat ji pokaždé nemusíte pokud proměnou nadm_vyska_paty vytvoříte mimo funkci jako globální (jak už psal Honza Buriánek)
pak potom co do ní bude v then() uložená hodnota k ní můžete přistupovat znovu i z jiných funkcí
když to vezmu zjednodušeně a volal bych to takto
let nadm_vyska_paty=0;
getElevation(lng_end + ',' + lat_end).then( function(value) {
nadm_vyska_paty=value
console.log(nadm_vyska_paty);
})
alert("XXX")
console.log(nadm_vyska_paty);
vrátí v konzoli
470
470
ptotože ten alert() pozastaví kod a než ho zavřete tak then() už má má vrácenou hodnotu a je uložena v nadm_vyska_paty
Jan Horinek
24.5.2024 v 19:05
Takže ten Alert je jediné řešení jak pozastavit kód? Ten se mi tam moc nehodí.
Jan Kuchař
reagoval na příspěvek
od Jan Horinek
24.5.2024 v 20:24
Ne jsou i jiné možnosti to bylo jen pro rychlou ukázku že se skutečně do té promene ta hodnota uloží a je k použití i mimo funkci. Už ale nejsem u PC tak jedině až zitra
Jan Horinek
24.5.2024 v 21:25
To vnější volání za Alertem mi vrací 0 (úvodní deklarace globální proměnné je 'let nadm_vyska_paty = 0').
To vnitřní vrací 470.
Jan Buriánek
24.5.2024 v 23:26
Jsem na vikend mimo, taky nejsem u PC. Co to tu ale ctu na mobilu, tak ano, promena ma po deklaraci 0, a po chvili se "sama" zmeni na 470. To tak je, to je chovani async funkci. Jakmile se do globalni promene hodmota ulozi navratem, tak uz tam zustane i pro dalsi pouziti. Dokud ji nekde neprepisete.
Proste pouzit ji.muzete az po navratu. A navrat vznika sam. Klidne i vic jak jednu vterinu po poptavce, zalezi na rychlosti internetu a vytizenosti serveru. Vas kod uz je davno vykonan, to trva milisekundy. Tomu musite kod uzpusobit. Lze treba deklarovat promenou jako = -1 a pak porovnavat, zda uz je plusova. Dokud ne, tak nebylo vraceno.
Ale realne se to programuje tak, ze tteba vykresleni se provede samo, spustene samo navratem, protoze hodnota uz je znama.