API-Aufruf in JavaScript

JavaScriptJavaScriptBeginner
Jetzt üben

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einleitung

In diesem Lab lernen Sie die wesentlichen Fähigkeiten für die Interaktion mit Web-APIs mithilfe von modernem JavaScript. Sie werden die fetch-API erkunden, ein leistungsstarkes und flexibles Werkzeug, das in Webbrowsern integriert ist, um asynchrone Netzwerkanfragen zu stellen. Das Hauptziel ist es, zu verstehen, wie Daten von einem Server angefordert, die Antwort verarbeitet und potenzielle Fehler verwaltet werden, was eine grundlegende Fähigkeit für die Erstellung dynamischer Webanwendungen darstellt.

Sie beginnen damit, eine grundlegende GET-Anfrage zu stellen, um Daten abzurufen, und lernen dann, wie Sie die Antwort verarbeiten, sie als JSON parsen und die abgerufenen Daten in einem HTML-Element anzeigen. Das Lab behandelt auch wichtige Aspekte wie die Implementierung robuster Fehlerbehandlung, das Stellen von POST-Anfragen zum Senden von Daten an einen Server und die Authentifizierung Ihrer Anfragen mithilfe eines API-Schlüssels.

Eine grundlegende GET-Anfrage mit der fetch API stellen

In diesem Schritt lernen Sie, wie Sie eine grundlegende API-Anfrage in JavaScript durchführen: eine GET-Anfrage. Wir werden die fetch-API verwenden, ein modernes, leistungsstarkes und flexibles Werkzeug, das in allen modernen Webbrowsern integriert und in Node.js 18+ Umgebungen verfügbar ist. Es ermöglicht uns, Ressourcen asynchron von einem Server anzufordern.

Die fetch-Funktion basiert auf Promises, was bedeutet, dass sie ein Promise zurückgibt, das sich zur Response dieser Anfrage auflöst, unabhängig davon, ob sie erfolgreich war oder nicht. Dies ermöglicht es uns, das Ergebnis der asynchronen Operation zu verarbeiten, wenn sie abgeschlossen ist.

Zuerst erstellen wir eine Datei, um unseren Code zu schreiben. Erstellen Sie im Dateiexplorer auf der linken Seite Ihres Bildschirms eine neue Datei namens index.js im Verzeichnis ~/project.

Für dieses Beispiel verwenden wir die JSONPlaceholder API. Dies ist eine kostenlose, gefälschte Online-REST-API, die sich perfekt zum Testen und Prototyping eignet. Wir werden ein einzelnes "todo"-Element anfordern.

Fügen Sie nun den folgenden Code zu Ihrer index.js-Datei hinzu. Dieser Code definiert die API-Endpunkt-URL und verwendet fetch, um eine GET-Anfrage zu stellen.

// Define the API URL for a single todo item
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";

// Make a GET request using the fetch API
fetch(apiUrl)
  .then((response) => {
    // The fetch function returns a promise.
    // The first .then() block receives the Response object.
    // We need to call the .json() method on the response to parse the body text as JSON.
    return response.json();
  })
  .then((data) => {
    // The second .then() block receives the parsed JSON data.
    console.log("Data fetched successfully:");
    console.log(data);
  })
  .catch((error) => {
    // The .catch() block will execute if any error occurs during the fetch operation.
    console.error("Error fetching data:", error);
  });

Lassen Sie uns den Code aufschlüsseln:

  • apiUrl: Wir speichern die URL des API-Endpunkts, mit dem wir kommunizieren möchten, in einer Konstante.
  • fetch(apiUrl): Dies initiiert die GET-Anfrage an die angegebene URL und gibt ein Promise zurück.
  • .then(response => response.json()): Wenn sich das Promise auflöst, wird diese Funktion aufgerufen. Das response-Objekt ist nicht die eigentlichen JSON-Daten, sondern eine Darstellung der gesamten HTTP-Antwort. Wir rufen die Methode response.json() auf, um den JSON-Body-Inhalt zu extrahieren, was selbst ein weiteres Promise zurückgibt.
  • .then(data => { ... }): Dieses zweite .then() verarbeitet das von response.json() zurückgegebene Promise. Der Parameter data enthält nun das tatsächliche JSON-Objekt von der API. Wir protokollieren diese Daten in der Konsole.
  • .catch(error => { ... }): Wenn das Promise an irgendeinem Punkt abgelehnt wird (z. B. aufgrund eines Netzwerkfehlers), fängt dieser Block den Fehler ab und protokolliert ihn in der Konsole.

Um Ihr Skript auszuführen und das Ergebnis zu sehen, öffnen Sie ein neues Terminal in der WebIDE und führen Sie den folgenden Befehl aus:

node ~/project/index.js

Sie sollten die abgerufenen Daten in Ihrer Konsole sehen, die ein einzelnes "todo"-Element von der API darstellen.

Erwartete Ausgabe:

Data fetched successfully:
{ userId: 1, id: 1, title: 'delectus aut autem', completed: false }
JavaScript fetch API GET request example

Antwort verarbeiten und JSON-Daten parsen

In diesem Schritt werden wir uns eingehender mit der Verarbeitung der Antwort eines API-Aufrufs befassen. Wenn Sie fetch verwenden, sendet der Server ein Response-Objekt zurück. Wir werden untersuchen, was dieses Objekt enthält und wie wir die JSON-Daten aus seinem Body korrekt parsen können, um sie in Ihrer Anwendung zu verwenden.

Das Response-Objekt, das Sie im ersten .then()-Block erhalten, sind nicht die Daten selbst. Es ist eine Darstellung der gesamten HTTP-Antwort, einschließlich Statuscodes (wie 200 für OK), Header und des Antwort-Bodys. Der Body ist ein Datenstrom, und um ihn zu verwenden, müssen Sie ihn lesen.

Die fetch-API bietet hierfür mehrere Methoden, wie z. B. .text() für reinen Text und .json() zum Parsen von JSON-Daten. Die Methode .json() liest den Antwortstrom bis zum Ende und gibt ein neues Promise zurück, das sich mit dem Ergebnis des Parsens des Body-Texts als JavaScript-Objekt auflöst. Deshalb verketten wir ein zweites .then(), um mit den eigentlichen Daten zu arbeiten.

Wir werden unsere ~/project/index.js-Datei ändern, um dies zu demonstrieren. Anstatt nur das gesamte Datenobjekt zu protokollieren, werden wir spezifische Eigenschaften daraus abrufen und protokollieren, um zu zeigen, dass wir mit einem regulären JavaScript-Objekt arbeiten.

Aktualisieren Sie den Inhalt Ihrer ~/project/index.js-Datei mit dem folgenden Code:

// Define the API URL for a single todo item
const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";

fetch(apiUrl)
  .then((response) => {
    // The response.json() method parses the JSON body of the response
    // and returns a promise that resolves with the resulting JavaScript object.
    return response.json();
  })
  .then((data) => {
    // Now 'data' is a JavaScript object. We can access its properties.
    console.log("Successfully parsed JSON data:");
    console.log(`Todo Title: ${data.title}`);
    console.log(`Is Completed: ${data.completed}`);
  })
  .catch((error) => {
    // The .catch() block will execute if any error occurs during the fetch operation.
    console.error("Error fetching or parsing data:", error);
  });

In diesem aktualisierten Code empfängt der zweite .then()-Block nun die data als JavaScript-Objekt. Wir verwenden Template-Literale (die Syntax mit Backticks `), um Zeichenketten zu erstellen, die die Werte von data.title und data.completed enthalten, was zeigt, dass das JSON erfolgreich geparst wurde.

Führen Sie das Skript nun erneut in Ihrem Terminal aus, um die neue Ausgabe zu sehen:

node ~/project/index.js

Sie sehen eine strukturiertere Ausgabe, die bestätigt, dass Sie erfolgreich auf die Eigenschaften des geparsten JSON-Objekts zugegriffen haben.

Erwartete Ausgabe:

Successfully parsed JSON data:
Todo Title: delectus aut autem
Is Completed: false

Abgerufene Daten in einem HTML-Element anzeigen

In diesem Schritt lernen Sie, wie Sie die von einer API abgerufenen Daten auf einer Webseite anzeigen. Während das Protokollieren von Daten in der Konsole für die Entwicklung nützlich ist, ist das eigentliche Ziel oft, diese Informationen dem Benutzer zu präsentieren. Dies erfordert eine HTML-Datei zur Strukturierung des Inhalts und JavaScript zur Manipulation des Document Object Model (DOM).

Zuerst benötigen wir eine HTML-Datei. Erstellen Sie im Dateiexplorer auf der linken Seite eine neue Datei namens index.html im Verzeichnis ~/project.

Fügen Sie Ihrer index.html-Datei die folgende grundlegende HTML-Struktur hinzu. Diese Datei enthält eine Überschrift und ein div-Element mit der ID data-output, das als Container für unsere abgerufenen Daten dient. Das <script>-Tag am Ende des Body stellt sicher, dass unser JavaScript ausgeführt wird, nachdem die HTML-Elemente geladen wurden.

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>API Data Display</title>
  </head>
  <body>
    <h1>Fetched Todo Item</h1>
    <div id="data-output">
      <p>Loading data...</p>
    </div>
    <script src="index.js"></script>
  </body>
</html>

Als Nächstes müssen Sie Ihre ~/project/index.js-Datei ändern, um mit diesem HTML zu interagieren. Anstatt in die Konsole zu protokollieren, sucht das Skript das div-Element anhand seiner ID und aktualisiert dessen Inhalt mit den Daten von der API.

Ersetzen Sie den Inhalt von ~/project/index.js durch den folgenden Code:

const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";

// Select the HTML element where we will display the data
const outputElement = document.getElementById("data-output");

fetch(apiUrl)
  .then((response) => response.json())
  .then((data) => {
    // Once we have the data, we update the HTML content.
    // We use innerHTML to replace the "Loading..." message with structured data.
    outputElement.innerHTML = `
      <p><strong>Title:</strong> ${data.title}</p>
      <p><strong>Completed:</strong> ${data.completed}</p>
    `;
  })
  .catch((error) => {
    // If an error occurs, display an error message to the user.
    outputElement.textContent = "Failed to load data.";
    console.error("Error fetching data:", error);
  });

Um das Ergebnis zu sehen, müssen Sie diese Dateien nun über einen Webserver bereitstellen. Die LabEx-Umgebung enthält Python, das über einen einfachen integrierten Webserver verfügt.

  1. Öffnen Sie ein neues Terminal in der WebIDE.
  2. Starten Sie den Webserver, indem Sie den folgenden Befehl ausführen. Dies stellt die Dateien im aktuellen Verzeichnis (~/project) auf Port 8080 bereit.
python3 -m http.server 8080
  1. Die LabEx-Plattform erkennt diesen laufenden Dienst und stellt einen "Web 8080"-Tab zur Vorschau Ihrer index.html-Seite bereit.
Web server running in terminal and preview tab

Sie sollten nun Ihre Webseite sehen, auf der der Titel und der Abschlussstatus des abgerufenen "todo"-Elements angezeigt werden und die anfängliche Nachricht "Loading data..." ersetzt wird.

Fehlerbehandlung für API-Aufrufe implementieren

In diesem Schritt werden wir unseren API-Aufruf robuster gestalten, indem wir eine ordnungsgemäße Fehlerbehandlung implementieren. API-Anfragen können aus verschiedenen Gründen fehlschlagen, z. B. wegen einer falschen URL, Netzwerkproblemen oder serverseitigen Problemen. Es ist entscheidend, diese potenziellen Fehler ordnungsgemäß zu behandeln, um eine bessere Benutzererfahrung zu bieten.

Ein wichtiger Punkt bei der fetch-API ist, dass ihr Promise bei HTTP-Fehlerstatuscodes wie 404 (Not Found) oder 500 (Internal Server Error) nicht abgelehnt wird. Es wird nur abgelehnt, wenn ein Netzwerkfehler auftritt, der die vollständige Ausführung der Anfrage verhindert. Um HTTP-Fehler zu behandeln, müssen wir die Eigenschaft response.ok überprüfen, die für erfolgreiche Antworten (Statuscodes 200-299) true ist.

Wir werden unser ~/project/index.js aktualisieren, um den Antwortstatus zu überprüfen und potenzielle Fehler zu behandeln.

Ersetzen Sie den Inhalt Ihrer ~/project/index.js-Datei durch den folgenden Code. Wir fügen eine Überprüfung im ersten .then()-Block hinzu.

const apiUrl = "https://jsonplaceholder.typicode.com/todos/1";
const outputElement = document.getElementById("data-output");

fetch(apiUrl)
  .then((response) => {
    // Check if the response was successful.
    // The 'ok' property is a boolean that is true if the status code is in the 200-299 range.
    if (!response.ok) {
      // If not, we throw an error which will be caught by the .catch() block.
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .then((data) => {
    outputElement.innerHTML = `
      <p><strong>Title:</strong> ${data.title}</p>
      <p><strong>Completed:</strong> ${data.completed}</p>
    `;
  })
  .catch((error) => {
    // Display a user-friendly error message in the HTML element.
    outputElement.textContent = "Failed to load data. Please try again later.";
    // Log the technical error to the console for debugging purposes.
    console.error("Error fetching data:", error);
  });

Um unsere Fehlerbehandlung in Aktion zu sehen, verwenden wir absichtlich eine ungültige API-URL. Ändern Sie die apiUrl in ~/project/index.js, sodass sie auf eine nicht vorhandene Ressource verweist. Dies führt dazu, dass die API einen 404 Not Found-Fehler zurückgibt.

Ändern Sie diese Zeile in Ihrer index.js-Datei:
const apiUrl = 'https://jsonplaceholder.typicode.com/todos/1';

Zu dieser:
const apiUrl = 'https://jsonplaceholder.typicode.com/invalid-path/1';

Sehen wir uns nun das Ergebnis an. Wenn Ihr Python-Webserver aus dem vorherigen Schritt noch läuft, aktualisieren Sie einfach den Vorschau-Tab in Ihrem Browser. Wenn Sie ihn gestoppt haben, starten Sie ihn erneut im Terminal:

python3 -m http.server 8080

Öffnen Sie dann die Vorschau. Anstelle der Daten sollten Sie die Fehlermeldung auf der Seite sehen, da unsere if (!response.ok)-Prüfung den 404-Fehler abgefangen hat.

Erwartete Ausgabe auf der Webseite:

Failed to load data. Please try again later.

Wichtig: Bevor Sie mit dem nächsten Schritt fortfahren, denken Sie daran, die apiUrl wieder auf die korrekte zurückzusetzen: https://jsonplaceholder.typicode.com/todos/1.

Eine POST-Anfrage zum Senden von Daten erstellen

In diesem Schritt lernen Sie, wie Sie Daten mithilfe einer POST-Anfrage an einen Server senden. Bisher haben wir nur Daten abgerufen (oder "GET"). Eine POST-Anfrage wird verwendet, um Daten an eine bestimmte Ressource zu übermitteln, was oft eine Zustandsänderung oder die Erstellung eines neuen Eintrags auf dem Server bewirkt.

Dazu müssen wir der fetch-Funktion weitere Informationen bereitstellen, darunter die Anfrage-Methode, Header zur Beschreibung der von uns gesendeten Daten und die Daten selbst im Anfrage-Body.

Zuerst aktualisieren wir unsere ~/project/index.html-Datei, um ein Formular einzufügen. Dies ermöglicht uns die Eingabe von Daten, die wir dann an die API senden können. Ersetzen Sie den gesamten Inhalt von index.html durch Folgendes:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>POST Request Example</title>
  </head>
  <body>
    <h1>Create a New Todo Item</h1>
    <form id="add-todo-form">
      <input
        type="text"
        id="todo-title"
        placeholder="Enter a new todo title"
        required
      />
      <button type="submit">Add Todo</button>
    </form>
    <hr />
    <h2>Server Response:</h2>
    <div id="response-output"></div>

    <script src="index.js"></script>
  </body>
</html>

Dieses HTML erstellt ein einfaches Formular mit einem Texteingabefeld und einem Absende-Button sowie einem div zur Anzeige der Serverantwort.

Als Nächstes ersetzen wir den gesamten Code in ~/project/index.js, um die Formularübermittlung zu verarbeiten und eine POST-Anfrage zu stellen.

Ersetzen Sie den Inhalt von ~/project/index.js durch den folgenden Code:

// The API endpoint for creating new todos
const apiUrl = "https://jsonplaceholder.typicode.com/todos";

// Get the form and the response output element from the DOM
const todoForm = document.getElementById("add-todo-form");
const responseOutput = document.getElementById("response-output");

// Add an event listener for the form's submit event
todoForm.addEventListener("submit", function (event) {
  // Prevent the default form submission behavior
  event.preventDefault();

  // Get the title from the input field
  const todoTitle = document.getElementById("todo-title").value;

  // The data we want to send in the POST request
  const newTodo = {
    title: todoTitle,
    completed: false,
    userId: 1
  };

  // The options for the fetch request
  const requestOptions = {
    method: "POST",
    headers: {
      "Content-Type": "application/json"
    },
    body: JSON.stringify(newTodo)
  };

  // Make the POST request
  fetch(apiUrl, requestOptions)
    .then((response) => {
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      // The API returns the created object, including a new 'id'
      return response.json();
    })
    .then((data) => {
      // Display the server's response in our output div
      responseOutput.innerHTML = `<p>Successfully created todo!</p><pre>${JSON.stringify(data, null, 2)}</pre>`;
    })
    .catch((error) => {
      responseOutput.textContent = "Failed to create todo.";
      console.error("Error:", error);
    });
});

Lassen Sie uns das neue requestOptions-Objekt aufschlüsseln:

  • method: 'POST': Dies teilt fetch mit, eine POST-Anfrage durchzuführen.
  • headers: { 'Content-Type': 'application/json' }: Dieser Header informiert den Server darüber, dass die Daten im Body im JSON-Format vorliegen.
  • body: JSON.stringify(newTodo): Dies sind die tatsächlichen Daten, die wir senden. Sie müssen in einen JSON-String konvertiert werden, bevor sie gesendet werden.

Starten Sie nun erneut Ihren Webserver, falls er nicht läuft:

python3 -m http.server 8080

Öffnen Sie die Vorschau, geben Sie einen Titel für ein neues Todo-Element in das Eingabefeld ein und klicken Sie auf die Schaltfläche "Add Todo". Sie sollten eine Erfolgsmeldung und die vom Server zurückgegebenen Daten sehen, einschließlich der neuen id für das von Ihnen "erstellte" Element.

Example of successful POST request response

Anfragen mit einem API-Schlüssel authentifizieren

In diesem Schritt lernen Sie, wie Sie Ihre API-Anfragen mit einem API-Schlüssel authentifizieren. Viele APIs erfordern eine Authentifizierung, um den Benutzer zu identifizieren, den Datenzugriff zu steuern und die Nutzung zu verfolgen. Ein API-Schlüssel ist eine eindeutige Zeichenkette, die Sie Ihrer Anfrage beifügen, um nachzuweisen, dass Sie die Berechtigung zur Nutzung der API haben.

Es gibt verschiedene Möglichkeiten, einen API-Schlüssel zu senden, aber eine gängige und sichere Methode ist die Aufnahme in die Anfrage-Header, typischerweise unter Verwendung des Authorization-Headers.

Für dieses Beispiel simulieren wir das Abrufen geschützter Benutzerdaten, die einen API-Schlüssel erfordern. Wir werden unseren Code ändern, um einen Authorization-Header mit einem "Bearer"-Token einzufügen, was eine Standardmethode zur Übermittlung von Authentifizierungsdaten ist.

Zuerst vereinfachen wir unsere ~/project/index.html-Datei, um nur die abgerufenen Benutzerdaten anzuzeigen. Ersetzen Sie deren Inhalt durch Folgendes:

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <title>Authenticated API Request</title>
  </head>
  <body>
    <h1>User Profile (Protected)</h1>
    <div id="user-profile">
      <p>Loading user data...</p>
    </div>
    <script src="index.js"></script>
  </body>
</html>

Als Nächstes ersetzen Sie den Inhalt von ~/project/index.js durch den folgenden Code. Dieses Skript führt eine GET-Anfrage aus, um Benutzerdaten abzurufen und einen gefälschten API-Schlüssel in den Headern einzufügen.

// Define the API URL for a user's profile
const apiUrl = "https://jsonplaceholder.typicode.com/users/1";

// In a real application, you would get this key from your API provider.
const apiKey = "YOUR_SECRET_API_KEY_HERE";

// Select the HTML element for output
const userProfileElement = document.getElementById("user-profile");

// Create the request options object, including the headers for authentication
const requestOptions = {
  method: "GET",
  headers: {
    Authorization: `Bearer ${apiKey}`
  }
};

// Make the authenticated GET request
fetch(apiUrl, requestOptions)
  .then((response) => {
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    return response.json();
  })
  .then((data) => {
    // Display the fetched user data
    userProfileElement.innerHTML = `
      <p><strong>Name:</strong> ${data.name}</p>
      <p><strong>Email:</strong> ${data.email}</p>
      <p><strong>Website:</strong> ${data.website}</p>
    `;
  })
  .catch((error) => {
    userProfileElement.textContent = "Failed to load user profile.";
    console.error("Error:", error);
  });

In diesem Code:

  • Wir definieren einen Platzhalter apiKey.
  • Wir erstellen ein requestOptions-Objekt.
  • Innerhalb von headers fügen wir einen Authorization-Schlüssel hinzu. Der Wert Bearer ${apiKey} ist ein gängiges Format, bei dem "Bearer" der Token-Typ ist, gefolgt vom Schlüssel selbst.

Hinweis: Die von uns verwendete JSONPlaceholder-API ist öffentlich und erfordert tatsächlich keinen API-Schlüssel. Sie wird diesen Header einfach ignorieren. Dieser Code demonstriert jedoch die Standardmethode, die Sie für viele reale APIs verwenden würden, die eine Authentifizierung erfordern.

Um das Ergebnis zu sehen, starten Sie Ihren Webserver, falls er noch nicht läuft:

python3 -m http.server 8080

Öffnen Sie dann die Vorschau. Die Seite wird erfolgreich geladen und das Profil des Benutzers angezeigt, was zeigt, dass Sie eine authentifizierte API-Anfrage korrekt strukturiert haben.

Zusammenfassung

In diesem Lab haben Sie gelernt, wie Sie mit der modernen fetch-API eine API in JavaScript aufrufen. Sie haben mit einer einfachen GET-Anfrage begonnen, um Daten von einem öffentlichen API-Endpunkt abzurufen. Sie haben geübt, die asynchrone Natur von fetch mithilfe von Promises zu handhaben, indem Sie .then()-Blöcke verknüpft haben, um die Antwort zu verarbeiten und den Body-Text als JSON zu parsen. Zu den wichtigsten Fähigkeiten gehörten die dynamische Anzeige der abgerufenen Daten innerhalb eines HTML-Elements und die Implementierung einer robusten Fehlerbehandlung mit einem .catch()-Block zur Verwaltung potenzieller Netzwerkfehler.

Aufbauend auf diesen Grundlagen haben Sie untersucht, wie Daten an einen Server gesendet werden, indem Sie eine POST-Anfrage mit den erforderlichen Headern und einer JSON-Nutzlast konstruiert und ausgeführt haben. Schließlich haben Sie eine gängige Methode zur Sicherung der API-Kommunikation durch Authentifizierung Ihrer Anfragen kennengelernt, die die Einbeziehung eines API-Schlüssels zur Erlangung autorisierten Zugriffs auf geschützte Ressourcen beinhaltete.