ugrás a tartalomhoz

fetch - másik domainről (meg úgy egyáltalán... :) )

mind1 valami név · 2022. Május. 9. (H), 09.59
Valakinek segíteni akartam egy primitív ajax-os problémát megoldani, akkor botlottam a JS fetch funkcióba.
Próbálom megérteni, de nem megy.

A nulladik gond, hogy nodejs interpreterből nem fut. Erre van valami egyszerű (!) workaround, hogy böngészős eszközöket használjak cli alapon?

Az elsődleges gond, hogy a "let resp=fetch("https://example.com/", {method:'GET', mode:'cors'});" következetesen hibára fut az oldal sajátjától eltérő domain miatt.

A másodlagos, hogy számomra borzasztóan idegen a JS szintaxis. Hogyan tudom ebből a Promise nevű ojjektumból kivenni a lekért oldal kódját?

Pythonban mindez nagyon egyszerű, de itt...
 
1

v17.5

Endyl · 2022. Május. 9. (H), 12.14
v17.5-től van fetch() nodejs-ben (tehát a workaround vagy a frissítés, vagy egy csomag telepítése, ami implementálja a funkciót a remélhetőleg megfelelő szintaxissal). De hiába az egyik kedvenc nyelvem a js, ha cli, akkor már én is inkább pythonozok.

Promise-okat legolvashatóbban async/awaittel lehet kezelni.
async function doSomething() {
  const response = await fetch(/* valami */);
  const text = await response.text();
  // ...
  return result;
}
Async kódon belül simán try-catch blokkal tudod elkapni a promise rejectiont.

Persze ha valahol sync kódból kell az async eredménye, akkor jön a hagyomásos callbackes promise kezelés (ahol az egyes callbackek megkapják a vonatkozó visszatérési értéket vagy a dobott kivételt paraméterként):
doSomething().then(onSuccessFunc, onErrorFunc);
// vagy
doSomething().then(onSuccessFunc).catch(onErrorFunc);
A második talán szebb, de észben kell tartani, hogy az nem csak a doSomething() hibáit kapja el, hanem az onSuccessFunc-ét is. Esete válogatja, hogy ez kívánatos-e.

Meg érdemes elolvasni az MDN fetch() doksiját is, vannak benne hasznos dolgok.

szerk.: Most látom, hogy csak az elsődleges kérdésre nem válaszoltam még. Milyen hibára fut pontosan a cors kérés? Ahonnan fetchelni próbálsz, ott kifejezetten meg kell engedniük fejlécekkel, hogy cross origin el lehessen őket érni.
2

Köszi!A pythonban

mind1 valami név · 2022. Május. 9. (H), 12.48
Köszi!

A pythonban mélységesen egyetértek. Sőt... :)
Csak macerás a browseres debug, ezért gondoltam, hogy cli alapon talán egyszerűbb megtalálni a hibákat, amíg csak ismerkedni próbálok a nyelvvel és ennek kapcsán került elő, hogy bizony a node interpreter nem ad mindent ami a browserben van. Létezik valami browser-env npm, most próbálom újra felrakni, mert telihányta a logot deprecated jelzésekkel, épp csak nem tudtam eldönteni, hogy én rontottam el valamit vagy eleve a csomag felejtős.

Sync kód, miután még csak parancssorból indítgatnék ezt-azt, de pont az (volt?) a gondom, hogy a .then() zárójelei közt hogyan férek hozzá a text()-hez, mert minden eddigi próbálkozásom eredménye az volt, hogy "undefined" vagy az, hogy "non existent nemtudommi".
Az MDN-t olvasgattam egyébként, csak nincsenek meg igazán a JS alapok, ami nem kis szívással jár ilyenkor. :D
(pl. még most sem értem teljesen a ... .then( a => ...) működését, mert sehogy sem akarja megtalálni a Response object metódusait, változóit stb. Sajnos töröltem a próbálkozásom nyomait, szóval majd nekiugrok újra, akkor tudok hibás kódot mutatni...


szerk: :) - oops... akkor ezt véletlenül jól értettem, hogy nem a kliens oldalon akad el a kérés, hanem a szerver utasítja el. Mondjuk sok értelmét nem látom, ha jól értem a célját, miszerint illetéktelen kódot injektálva egy oldalba ne lehessen megfertőzni a látogatók gépét. Hiszen ebben az esetben pont a rosszindulatú szerverre van bízva, hogy engedi-e a kérést vagy sem. (vagy mégis félreértek valamit?)
4

Sync

Endyl · 2022. Május. 9. (H), 14.46
Szimplán sync kódban valami ilyesmi lehet:
fetch(/* ... */)
	.then(function (response) { return response.text(); })
	.then(function (text) { console.log('Forrás', text); });
// Vagy arrow függvényekkel
fetch(/* ... */)
	.then(response => response.text())
	.then(text => console.log('Forrás', text));
Ennek a lényege, hogy a then() hívás is egy promise-t ad vissza, ami a callback visszatérési értékével fog teljesülni. És a response.text() is async/promise, azért kell a második then.

Ha a saját oldaladba kerül rosszindulatú kód, az már XSS, az ellen a cors fejlécek valóban nem fognak védeni. Ez akkor jó, ha valaki be van jelentkezve a te oldaladon, és ellátogat a rosszindulató oldalra, akkor az ne tudja lekérni a teoldalad.com/privat-adatok oldalt, vagy hasonlót. Vagyis ez ugye alapból tiltva van cross-origin kérésként, de a fejlécekkel lazíthatsz ezen a szigoron, ha szeretnéd, hogy egy másik, megbízható origin mégis le tudjon kérni ilyen adatokat, vagy esetleg egy olyan API-t szolgáltatsz, aminél nem baj, ha random oldalakról is meg tudják hívni (stb, stb, elég mély téma, aminek nekem is mindig utána kell néznem, ha hozzá kell nyúlni :) ).

És akkor ott van még a CSRF is, amire figyelni kell.
5

No igen. Itt van az, hogy már

mind1 valami név · 2022. Május. 9. (H), 15.41
No igen. Itt van az, hogy már nem is tudok hosszabb szövegeket olvasni. :(
Most futottam neki negyedszer a CORS leírásának, most végre kezdem felfogni, hogy miről szól.
6

promise?

mind1 valami név · 2022. Május. 9. (H), 18.40
Egyébként ez a Promise mit jelent?
Mert a csekély angoltudásom és a szótár szerint is az ígéret szó és szinonimái. De az ide nem illik.
8

pedig de

Endyl · 2022. Május. 9. (H), 22.55
Nem tudom, hogy olvastam-e, vagy csak magamban gondolok rá úgy, de egy a jövőben elérhető érték ígérete :D
9

Nekem is ez jutott eszembe a

mind1 valami név · 2022. Május. 10. (K), 00.28
Nekem is ez jutott eszembe a szóról, csak nagyon erőltetettnek tűnt. :)
7

Tisztulnak a dolgok

mind1 valami név · 2022. Május. 9. (H), 19.19
https://stackoverflow.com/questions/31621964/cors-example-com

Sokadik nekifutásra és a fentit válaszoddal összerakva sikerült felfognom végre. A fentiek szerint nem én vagyok az egyetlen, aki "kissé" félreértette az egész történetet.

Amit viszont sohasem fogok megérteni: ha valaki olyat mer kérdezni a so-n, ami... hát nem egy triviális dolog, rögtön jönnek a hiénák mínuszolni.

Egyébként nem ártana megjegyeznem, hogy
1. proxy
2. ad- és egyéb block addonok
3. noscript
elég rendesen keresztbe tudnak tenni a tesztelgetésnek. :D
3

Kezd működni a dolog. A

mind1 valami név · 2022. Május. 9. (H), 14.32
Kezd működni a dolog. A "mode: 'cors'" pl. rossz ötlet volt részemről, no-cors esetében legalább működik. Bár még nem tiszta, hogy miért így...
Folyt. köv. :)
10

Cors

bzozoo · 2022. Júl. 31. (V), 10.10
A cors-ot bele sem kell tenni az optionsba mert úgy tudom, hogy az a default.
A szerveroldalon kell elintézni, hogy a kérelmező oldal kéréseit fogadja.
11

fetch - hogy kapom vissza az adatot?

mind1 valami név · 2023. Már. 28. (K), 23.53
Nem értem.

let b=8; // tökmindegy, létezzen a változó
fetch("/api/param").then((response) => response.json()).
    then((adat) => { b=adat });
Ha a js konzolon írom be (firefox -> f12), akkor szépen visszaadja a b-be a lekért json-t.
Beírva az oldal kódjába egy függvény belsejébe és <script src="..." defer></script> betöltve nem megy.
A b következetesen az eredeti értékén marad, holott a második .then-ben ha kiíratom az adat értékét, ott rendben van.
Van valakinek ötlete, hogy mit nézek el már megint?

Valahogy úgy érzem, a chatgpt épp annyira nem ért hozzá, mint én :D Ugyanezt javasolta, amit itt leírtam. De az nem működik.
Vagy a fetch-ből tényleg kizárólag callback függvényen keresztül lehet kiszedni a visszakapott értékeket?
Azt is készséggel elfogadnám, hogy a függvénybe rakott blokkból nem látszik a külső változó, de akkor konzolról miért működik mégis?


Hát igen, úgy néz ki, hogy amit kézzel írok be, annak van ideje kivárni az aszinkron futás végét, ha meg egyben fut le, akkor még nem ér oda az eredmény.

ChatGPT hozza a szokott formáját: beírtam neki a függvény definíciót úgy, hogy a második then így nézett ki: .then((data) => ????); Utána következő sorba egy console.log(xx);
És megkérdeztem, hogy mit írjak a ???? helyére, hogy a console.log már a helyes értéket kapja. Erre egyszerűen beemelte a console.log-ot a then belsejébe. :D
Mikor jeleztem, hogy ez így nem jó, akkor hibaüzenettel végérvényesen leállt. :D

Az a gáz, hogy vagy részletes doksit találok, amiből per pillanat nem sokat értek, vagy olyan példát ahol a második then csak egy console.log, ami számomra értékelhetetlen vagy az egyetlen használhatónak nevezhető variációt, ami egy callback függvényt használ. Azzal meg ugyanott vagyok: külső függvényből pont nem tudok beletúrni az épp futó függvény belsejébe.
12

Teljesebb kód?

Endyl · 2023. Már. 29. (Sze), 11.16
Mikor van még eredeti értékén a b?

let b=8;
fetch("/api/param").then((response) => response.json()).then((adat) => { b=adat });
console.log(b); // itt még tuti 8 a b értéke, mert a fetch async
setTimeout(() => {console.log(b)}, 2000); // ha két mp alatt lefut a kérés, akkor b már új értékkel van itt
Ha meg kvázi szinkronban akarsz dolgozni a kéréssel, akkor async/await-tel így lehet:
(async function() {
	let response = await fetch('/api/param');
	let data = await response.json();
	console.log(data);
})()
13

Végül is megfejtettem, ha

mind1 valami név · 2023. Már. 29. (Sze), 12.23
Végül is megfejtettem, ha nehezen is.
Szóval én abban a hitben voltam, hogy a .then() az megvárja amíg elkészül a Promise-ban ígért művelet és csak aztán megy tovább. Na ez volt a tévedés: a then is async módon működik, simán továbblép, miután ráfutott az interpreter, végrehajtja a mögötte lévő parancsokat, aztán majd, valamikor ő is lefut.

async function showdetails(e){
    let b = 8;
    const dbox = document.getElementById("statbox");
    const freetext = document.getElementById("stat_freetext");
    freetext.innerText = e.children[0].children[0].pathname;
    const apipath = "/api" + e.children[0].children[0].pathname;
    console.log("API path:" + apipath);
    const result = await fetch(apipath).then((resp) => resp.json())
            .then((data) => { b = data; console.log(b, data)} );
    //console.log(e.children[0].children[0]);
    console.log("B:", b);
    console.log("result", result)
    dbox.showModal();
    return false;
}
Elég ocsmány, nem szoktam ilyet, de most csak a megfejtés volt a lényeg, a kozmetikát hanyagoltam. Eredetileg az egész ugyanígy nézett ki, csak nem async függvény volt és ebből következően az await is hiányzott.

A legzavaróbb az egészben, hogy async fv. hívni egy html tagre ültetett eventből??? Ez meg milyen dolog? Működik, de pythonban én még ott tartottam, hogy async az csak async loop-on belül futhat, az onclick/oncontextmenu és társaik viszont nagyon nem azok, mert ott egyből visít az await miatt. :) De akkor egy async függvényt miért fogad el?
14

async -> promise

Endyl · 2023. Már. 29. (Sze), 12.37
Egy async függvény kintről nézve annyit tesz, hogy promise-t ad vissza, tehát bárhonnan hívhatod. Belülről meg használhatod az await-et, ami megvárja az utána jövő promise-t, és addig visszaadja a vezérlést.