Funktion mit fetch() soll kein Promise, sondern Daten liefern
ebody
- javascript
Hi,
kann man es vermeiden then
und catch
bei dem Aufruf der Funktion verwenden zu müssen? Die Funktion selbst wartet ja schon auf das Ergebnis. Wenn man in der Funktion und im Funktionsaufruf then
und catch
verwenden muss, erscheint es mir unnötig doppelt verwendet zu werden und falsch.
/* Variante 1 */
async function load_1(apiURL){
try{
// Ausführen der HTTP-Anfrage, um JSON-Daten abzurufen
const response = await fetch(apiURL);
// JSON-Response speichern
const json = await response.json();
// Daten zurückgeben
return await json.data;
} catch(err){
// Fehlerbehandlung
throw err;
}
}
const data1a = load_1('https://reqres.in/api/users/');
console.log('data1a',data1a); // => Promise
Wenn man load_1()
aufruft, soll die Funktion direkt die Daten und kein Promise liefern. Wie kann man das machen?
Gruß ebody
Hallo ebody,
Wenn man load_1() aufruft, soll die Funktion direkt die Daten und kein Promise liefern. Wie kann man das machen?
Gar nicht. Fetch ist asynchron, das wirst Du nicht los.
const json = await response.json(); // Daten zurückgeben return await json.data;
Öhm, der await für json.data ist unnötig. response.json() interpretiert das Request-Ergebnis als JSON-String und macht ein Objekt daraus. Damit ist die Asynchronität am Ende.
Für das Promise bleibt Dir nur
const data1a = await load_1('https://reqres.in/api/users/');
console.log('data1a',data1a); // => Promise
Wenn dieser Code auf dem Top-Level läuft, haut JS ihn Dir um die Ohren. Top-Level await ist nur in ECMAScript-Modulen zulässig. Das hat Konsequenzen:
Wenn das für deinen Code passt (oder dein Code passend gemacht werden kann), dann füge deinem Script-Statement ein type="module" hinzu und der Top-Level await ist möglich.
Alternative B ist das Einkapseln des ganzen Steuerung in eine weitere async-Funktion. Da geht immer ein await.
Alternative C ist
load_1('https://reqres.in/api/users/')
.then(data1a => console.log('data1a',data1a));
console.log("Huhu, hier bin ich!");
Wichtig ist bei .then, dass der Code im then erst läuft, wenn Fetch fertig ist. Der Huhu-Log wird hingegen ausgegeben, während der Fetch noch busy ist.
await ist Syntaxzucker, der einfach den ganzen Rest einer Funktion in einen then-Callback umwandelt.
Rolf
Hi Rolf,
vielen Dank. Ganz ehrlich verstehe ich das Prinzip nicht, also kann es nicht nachvollziehen (bezieht sich nicht auf deine Antwort). Es muss doch möglich sein, eine Funktion zu erstellen, mit der ich Daten abfrage. Diese Funktion wartet so lange bis die Daten geladen sind und gibt die Daten zurück. Ich dachte, dafür wären fetch
und await
gedacht.
Ruft man load_1('https://reqres.in/api/users/')
auf, erhält man also direkt die Daten.
Hintergrund ist, dass ich eine Klasse erstellen möchte, die eine Methode enthält, um Daten zu laden. Erstellt man eine Instanz und ruft die Methode auf fände ich es viel schöner, wenn man einfach const data = Data.load(url);
aufrufen muss, anstatt const data = Data.load(url).then...;
Wäre dann Ajax oder ein anderer Weg in dem Fall die bessere Alternative?
Gruß ebody
Hallo ebody,
sowohl fetch wie auch XMLHttpRequest (Ajax) arbeiten asynchron. JavaScript im Browser macht keine synchrone I/O, das kann nur node.js.
Es war einmal anders. Die open-Methode von XMLHttpRequest kennt einen async-Parameter, dem Du false übergeben kannst. Dann läuft der Request synchron ab.
Synchrone HTTP Requests im Hauptthread sind missbilligt. Die Browserhersteller sind dabei, dieses Szenario als Fehler zu definieren. NICHT MACHEN!!!
Wenn Du einen WebWorker erstellst, sind synchrone Requests zulässig. Aber ein WebWorker läuft selbst asynchron zum Hauptthread.
Es muss doch möglich sein, eine Funktion zu erstellen, mit der ich Daten abfrage. Diese Funktion wartet so lange bis die Daten geladen sind und gibt die Daten zurück.
In WebWorkern und in Batch-Tools, die mit Node.js laufen - ja.
In einem ereignisorientierten Umfeld - nein. Das trifft für Browser zu und für Serverdienste mit node.js. Dort ist JavaScript ein Tool zur Ereignisverarbeitung und jeder JavaScript-Aufruf muss schnell fertig werden, denn so lange ein Event verarbeitet wird, müssen alle übrigen warten. Ein Browser oder Server würden dadurch blockiert werden.
Das ist das Grundprinzip aller graphischen UIs - der User macht was und daraus resultieren Ereignisse. Diese werden ans Anwenderprogramm geschickt und eins nach dem anderen verarbeitet. Ein paar Ereignisse können in eine Queue gestellt werden, aber nur eine Handvoll, denn andernfalls würde eine langsame Verarbeitung dazu führen, dass der User nichts mehr tut, aber das Programm noch sekundenlang den Ereignissen hinterher hechelt. Deswegen blockiert das UI, wenn die Eventqueue voll ist.
Rolf