[MELDEN] Von der Vision zum Code: Ein Leitfaden zur Ausrichtung der Geschäftsstrategie auf die Ziele der Softwareentwicklung ist veröffentlicht!
HOL ES DIR HIER

API mit Express.js und Hadron erstellen

readtime
Last updated on
February 19, 2025

A QUICK SUMMARY – FOR THE BUSY ONES

TABLE OF CONTENTS

API mit Express.js und Hadron erstellen

Einführung

Zusammen mit den Leuten von Brainhub haben wir ein Tool entwickelt, das die Magie der Dependency Injection bietet, um die Implementierung der CRUD-API unterhaltsamer und einfacher zu gestalten.

Hadron ist ein leichtes Open-Source-Framework, das mit einigen Tools wie Express.js (derzeit ist Express das einzige unterstützte Webframework) und Datenbankverwaltungstools wie TypeORM verwendet werden kann. Hadron besteht sogar aus Paketen wie hadron-Serialization, die es ermöglichen, die von der API ausgegebenen Daten einfach zu strukturieren, auch wenn ausgewählte Felder nur für einige „Gruppen“ sichtbar sind.

Hadron wirkt sich nicht negativ auf die Backend-Leistung aus. Ziel ist es, die Erfahrung zu verbessern und gleichzeitig die API zu erstellen und zu warten und eine hohe Effizienz zu gewährleisten.

Ein kurzer Überblick über die Anwendungsfälle von Hadron +

Das Einrichten des Backends mit Hadron erfordert nur wenige Codezeilen. Zunächst zeige ich Ihnen, wie Sie mit Hilfe von Hello World eine einfache Hello World-Route einrichten Hadron und Express.js.

Express aus „Express“ importieren;
importiere Hadron aus '@brainhubeu /hadron-core';
importiere * als HadronExpress aus '@brainhubeu /hadron-express';

const app = neuer Express ();
const port = process.env.Port || 3000;

const config = {
Routen: {
Hallo Welt: {
Pfad: '/',
Methoden: ['GET'],
callback: () => 'Hallo Welt! ' ,
}
}
};

Hadron (
App,
[Hadronen-Express],
Konfiguration,
) .dann ((Behälter) => {
app.listen (port, () =>
console.log (`Hört auf http://localhost:${port} `),
);
})

Das Wichtigste hier ist der Konfiguration Objekt. Wir spezifizieren dort die Konfiguration für Hadron-Pakete (Routen für Hadron-Express). Die Konstruktormethode gibt ein Versprechen mit dem zurück Container Objekt, das für die Abhängigkeitsinjektion verwendet wird. Wir werden uns später in diesem Artikel eingehender damit befassen.

Wie Sie wahrscheinlich bemerkt haben, kann die Entwicklung einer größeren App ein Albtraum sein, wenn Sie mehr Hadron-Pakete verwenden. Das Konfigurationsobjekt wäre riesig — stell dir alle Routen dort vor. Natürlich können wir Routen einfach auf mehrere Dateien aufteilen und sie importieren.

Das ist der Ort, an dem Hadron-JSON-Anbieter Paket kommt rein. Mit diesem eigenständigen Paket können Sie den Pfad und die Erweiterungen für Dateien angeben, die automatisch für Sie importiert werden sollen.

Es ist sehr nützlich, um unsere Routen in verschiedene Dateien aufzuteilen. Standardmäßig akzeptiert das Hadron-Express-Paket Schlüssel Routenpfade in Hadrons Konfiguration, die eine Reihe von Pfaden und Erweiterungen akzeptiert und dann das Paket hadron-json-provider verwendet, um Routen aus diesen Dateien zu laden.

const config = {
Routenpfade: [
[
'. /routen/ *',
„uns“,
],
[
'. /Zusätzliche Routen/ *',
]
],
};

Hadron gegen Plain express.js

Erinnerst du dich an das Hadron? hat keinen Einfluss auf die Leistung Ihrer Backend-Anwendung — getestet mit API-Benchmark mit 10000 Durchläufen, die gleichzeitig abgetastet wurden: 10000.

Hadron bietet Ihnen den Raum und die Werkzeuge, die Produktivität und Wartbarkeit steigern über Ihr Projekt und erstellt eine abstrakte Ebene über Frameworks wie Express.js.

Der Hauptvorteil der Verwendung von Hadron ist, dass Sie schnell und einfach verschiedene Tools auswählen um Datenbanken zu verwalten, Sicherheit bieten, und gestalten Sie Ihre Ausgabe auf der Grundlage des Benutzertyps. Alles wird einfach für Sie erledigt und von Ihnen einfach konfiguriert.

Das Erstellen einer API mit Hadron ist so einfach, dass Sie Ihre Routen in verschiedene Dateien aufteilen können, ohne sich um Abhängigkeiten, Instanzen usw. zu kümmern. Dies liegt an der Dependency Injection, die in der Callback-Funktion der Route verwendet wird.

Wenn Sie ein Paket registrieren, wird es mit der bereitgestellten Konfiguration initialisiert und in den Container unter den spezifischen Schlüsseln abgelegt, die Sie später in den Callback-Funktionen der Route verwenden können.

Hadrons Abhängigkeitsinjektion

Hadron bietet die Möglichkeit, Daten oder Objektinstanzen in etwas zu speichern, das wir Container. Es speichert auch Daten, die von Hadron-Paketen initialisiert wurden, z. B. Datenbank-Repositorys im Paket hadron-typeorm.

Bei der Registrierung eines Artikels im Container können Sie eine der lebenslangen Optionen wählen. Diese sind:

  • value — das ist das Standardverhalten. Beim Abrufen von Daten aus dem Container erhalten Sie dasselbe zurück, was registriert wurde.
  • singleton — gibt immer dieselbe Instanz einer registrierten Klassen-/Konstruktorfunktion zurück.
  • transient — gibt immer eine neue Instanz einer registrierten Klassen-/Konstruktorfunktion zurück.

Die Dependency Injection wird in den Callbacks der Route verwendet, sodass Sie problemlos auf alle Containerwerte zugreifen können. Nehmen wir an, wir speichern eine Zeichenfolge Hello World in unserem Container unter der Schlüsselnachricht und wir möchten auf unserer Route darauf zugreifen.

importiere BodyParser aus 'Body-Parser';
Express aus „Express“ importieren;
importiere Hadron aus '@brainhubeu /hadron-core';
importiere * als HadronExpress aus '@brainhubeu /hadron-express';

const port = process.env.Port || 8080;
const expressApp = express ();
expressApp.use (bodyParser.json ());

Hadron (
ExpressApp,
[Hadronen-Express],
{
Routen: {
Basisroute: {
Pfad: '/',
Methoden: ['get'],
callback: ({}, {message}) => `Nachricht im Container gespeichert: $ {message} `,
},
},
},
) .dann ((Behälter) => {
container.register ('message', 'Hallo Welt');

ExpressApp.Listen (Anschluss);
console.log (`zuhören auf http://localhost:${port} `);
});

Nachdem Sie eine Anfrage an http://localhost:8080/ gesendet haben, erhalten Sie:

„Nachricht im Container gespeichert: Hello World“

Auf diese Weise können Sie auf Containerartikel zugreifen. In den meisten Paketen werden Artikel dort gespeichert, sodass Sie problemlos einige Aktionen ausführen oder die gewünschten Daten abrufen können.

Vielleicht denken Sie jetzt darüber nach, darauf zuzugreifen anfordern Variablen, die sehr oft in unseren Routen verwendet werden, wie Kopfzeilen, Parameter, Körper, abfragen usw.. Diese Daten werden als erster Parameter in der Funktion des Callbacks bereitgestellt.

Basisroute: {
Pfad: '/',
Methoden: ['get'],
Rückruf: ({headers}, {}) => JSON.stringify (headers),
},

In diesem Fall gibt die Antwort der Route das Header-Objekt der Anfrage zurück.

Hadron-Pakete im Schnellüberblick

Wir haben bisher nur wenige Pakete entdeckt, insbesondere hadron-express. Lassen Sie uns einige der offiziellen Hadron-Pakete besprechen.

Alle in diesem Artikel vorgestellten Beispiele sind hier bei GitHub erhältlich. Fühlen Sie sich frei, mit ihnen zu spielen.

ORM vom Typ Hadron

Dieses Paket umschließt und integriert die Typ ORM Paket mit Hadron. Es gibt uns die Möglichkeit, uns zu registrieren und darauf zuzugreifen Repositories oder Migrationen der einfache Weg.

Um eine Verbindung mit Ihrer Datenbank herzustellen, importieren Sie einfach das Paket hadron-typeorm und stellen das Verbindungsobjekt der Konfiguration von Hadron zur Verfügung.

Nehmen wir an, wir haben eine Tabelle mit Benutzern. Um einen Datensatz mit seiner ID abzurufen, verwenden wir einen Endpunkt wie /user/1. Unser Callback könnte so aussehen:

getUserById: {
Pfad: '/user/:id',
Methoden: ['get'],
Rückruf: async ({params}, {userRepository}) => ({
body: warte auf userRepository.findOneById (params.id),
}),
},

Sieht einfach aus, oder? Aber was ist mit einer Verbindung zu unserer Datenbank? Wie ich bereits erwähnt habe, müssen wir bei der Initialisierung von Hadron ein Verbindungsobjekt für unsere Konfiguration bereitstellen. Im folgenden Beispiel verwenden wir die MySQL-Datenbank.

importiere {User} aus '. /entity/Benutzer ';

konstante Verbindung: ConnectionOptions = {
name: 'mysql-verbindung',
Typ: 'mysql',
host: 'localhost',
Hafen: 3306,
benutzername: 'root',
Passwort: 'my-secret-pw',
Datenbank: 'Demo-App',
Entitäten: [Benutzer],
};

Um ein Repository in TypeORM zu erstellen, benötigen wir eine Entität. Hadron registriert dann ein Repository daraus und registriert sich unter dem Schlüssel, der den Entitätsnamen enthält und Endlager Suffix — Entität Nutzer wird sich in einem Container unter dem registrieren Benutzer-Repositorium Schlüssel.

Hadron-Serialisierung

Mit Serializer können Sie die Form Ihrer JSON-Ausgabe angeben.

Stellen Sie sich vor, ein Benutzer sendet eine Anfrage mit einem Authentifizierungstoken an die API. Mit einem Hadron-Serialisierungspaket können wir uns einfach um Felder kümmern, die dieser Benutzer aufgrund seiner Berechtigungen sehen wird.

Im folgenden Beispiel gibt es nur einen Endpunkt
/:Gruppe? (wir werden uns um zwei Gruppen kümmern, Mod und Admin).

In unserem Fall wird es eine Liste von Benutzern geben, die als Antwort für diese Endpunkte zurückgegeben werden. Jeder Benutzer sollte den Vor- und Nachnamen des Benutzers sehen, Benutzer in der Gruppe mod sollte auch eine E-Mail sehen und Administrator wird sie alle mit einem zusätzlichen ID-Feld sehen.

Dies sind die Daten, die wir verwenden werden:

[
{
„id“: 1,
„Vorname“: „John“,
„Nachname“: „Doe“,
„email“: "[email protected]
},
{
„id“: 2,
„Vorname“: „Adam“,
„lastName“: „Kowalski“,
„email“: "[email protected]
},
{
„id“: 3,
„Vorname“: „Rick“,
„LastName“: „Svannson“,
„email“: "[email protected]
}
]

Damit das Hadron-Serialisierungspaket funktioniert, müssen wir es initialisieren. Aber vorher sollten wir ein Schema für unsere Daten definieren. Wir können es in einer anderen Datei definieren oder einfach ein Objektliteral in Hadrons Konfiguration bereitstellen. Wir werden es als externe JSON-Datei speichern.

{
„name“: „Benutzer“,
„Eigenschaften“: [
{„name“: „id“, „type“: „string“, „groups“: ["admin"]},
{„name“: „Vorname“, „Typ“: „Zeichenfolge“},
{„name“: „Nachname“, „Typ“: „Zeichenfolge“},
{„Name“: „E-Mail“, „Typ“: „Zeichenfolge“, „Gruppen“: ["mod“, „admin"]}
]
}

Also, um es klarzustellen — ein Schema ist ein Objekt und sollte enthalten:

  • Name — einfach der Name des Schemas. Das benötigen wir, um das Schema bei der Serialisierung von Daten zu erkennen.
  • Eigenschaften — dieses Feld enthält eine Reihe von Objekten. Jedes Objekt enthält den Namen des Schlüssels, der serialisiert werden soll, den Typ und die Gruppen, für die es sichtbar sein soll (wenn Gruppen leer sind, sind sie für alle sichtbar).

<span class="colorbox1" fs-test-element="box1"><p>Beachten Sie, dass, wenn Sie in einem Schema keinen Schlüssel angeben, dieser nicht sichtbar ist!</p></span>

Okay, jetzt haben wir unsere Daten definiert und das Schema, das im Serialisierungspaket benötigt wird. Definieren wir als Nächstes unsere Hadron-Instanz. Unser index.js Datei sollte so aussehen:

Express aus „Express“ importieren;
importiere Hadron aus '@brainhubeu /hadron-core';
importiere * als HadronExpress aus '@brainhubeu /hadron-express';
importiere * als HadronSerialization aus '@brainhubeu /hadron-serialization';

Daten aus 'importieren. /data.json ';
importiere UserSchema aus '. /schemas/Benutzer.json ';

const app = neuer Express ();
const port = process.env.Port || 3000;

const routeCallback = (Serializer, Gruppe) =>
Ich verspreche alles (
data.map (user => serializer.serialize (user, [group], 'Benutzer'))
) .then (Benutzer => ({
Anzahl: Datenlänge,
Daten: Benutzer
});

Hadron (
App,
[Hadron Express, Hadron-Serialisierung],
{
Routen: {
Route mit Gruppe: {
Pfad: '/:group? ' ,
Methoden: ['GET'],
Rückruf: routeCallback,
}
},
Serialisierer: {
Schemas: [BenutzerSchema],
}
}
) .dann (Behälter => {
app.listen (port, () =>
console.log (`Hört auf http://localhost:${port} `),
);
})

Das obige Beispiel ist im Grunde ein Beispiel für eine ganze App, die mit Hadron erstellt wurde. Es ist also einfach, das Hadron-Serialisierungspaket einzurichten — alles, was wir tun müssen, ist Schemaobjekte zu deklarieren, die verwendet werden, um unsere Daten zu formen und sie in der Konfiguration bereitzustellen.

Als Nächstes, wenn wir unsere Daten serialisieren möchten, nehmen Sie einfach die Serializer Objekt aus dem Container und führe die serialise-Methode aus.

Hadron-Veranstaltungen

Das Hadron-Events-Paket ermöglicht es Ihnen, integrierte Ereignisse zu verwenden oder sogar Ihre eigenen benutzerdefinierten Ereignisse zu deklarieren, Listener an sie zu binden und sie einfach zu einem beliebigen Zeitpunkt des Anwendungslebenszyklus auszugeben.

Derzeit gibt es in Hadron nur wenige eingebaute Ereignisse, die in den Paketdokumenten aufgeführt sind, die Sie finden hier.

Um unsere einfachen Event-Handler zu initialisieren, müssen wir Listener für Ereignisse bereitstellen. Im folgenden Beispiel werden wir die Hadron-Events-Paketkonfiguration in der Bootstrapping-Funktion von hadron-core bereitstellen.

[...]
importiere Listener aus '. /Veranstaltungen/Zuhörer ';

Hadron (
App,
[Hadron Express, Hadron-Ereignisse],
{
routen: {/* [...] */},
Ereignisse: {
Zuhörer,
}
}
) .dann (Behälter => {
/* [ ... ] */
});

Also nehmen wir unsere Zuhörer in eine externe Datei auf. In unserem Beispiel werden wir versuchen HandleRequestCallbackEvent, das Ereignisse ausgibt, kurz bevor jede Anfrage erfolgt.

Standard exportieren [
{
name: 'Test',
event: 'handleRequestCallbackEvent',
Handler: (Daten,... Rest) => {
console.log ('handleRequestCallbackEvent', Daten);
console.log ('#####');
console.log (Rest);
}
},
];

Im Hadron-Events-Paket können wir auch unsere eigenen Ereignisse zu jedem Zeitpunkt des Anwendungslebenszyklus ausgeben. Wir warten auf 2 Ereignisse mit einem einfachen Namen wie Erfolgreiches Event und Ereignis scheitern. Wir werden dieses Ereignis dann ausgeben, wenn der Benutzer eine Anfrage sendet an /:Schlüssel, wenn der Schlüssel hat einen Wert von foo.

{
benutzerdefinierte EventRoute: {
Pfad: '/:key? ' ,
Methoden: ['GET'],
Rückruf: (Anfrage, {eventManager}) => {
const {params: {key}} = Anfrage;
const eventToEmit = (Schlüssel === 'foo' && 'SuccessEvent') || 'FailEvent';
eventManager.emitEvent (eventToEmit) (Schlüssel);
zurückkehren {
Körper: {
„key“: Schlüssel || „,
„eventEmited“: EventToEmit,
},
};
},
},
}

Und der letzte Schritt in unserem Beispiel wird die Implementierung von Listenern sein. Wie bereits erwähnt, werden wir 2 Listener erstellen, einen für SuccessEvent und einen für FailEvent.

Standard exportieren [
{
name: 'Erfolg',
event: 'SuccessEvent',
Handler: (Schlüssel,... Rest) => {
console.log (`Sie haben erfolgreich den Wert von $ {key} angegeben `);
}
},
{
name: 'Fehlgeschlagen',
Ereignis: 'FailEvent',
Handler: (Schlüssel,... Rest) => {
console.log (`Sie haben erfolgreich den Wert von $ {key} angegeben `);
}
},
];

Dadurch können wir diese benutzerdefinierten Ereignisse von jedem Ort in unserer App aus ausgeben. Der Einfachheit halber ist dieser Ort in unserem Beispiel der Rückruf der Anfrage.

Links

Über

Hadron und die offiziellen Pakete werden vom Brainhub-Entwicklungsteam verwaltet. Es wird von Brainhub finanziert und die Namen und Logos für Brainhub sind Marken von Brainhub Sp. z o.o.. Sie können sich andere Open-Source-Projekte ansehen, die von unseren Teamkollegen unterstützt/entwickelt wurden.

Frequently Asked Questions

No items found.

Our promise

Every year, Brainhub helps 750,000+ founders, leaders and software engineers make smart tech decisions. We earn that trust by openly sharing our insights based on practical software engineering experience.

Authors

Bianka Pluszczewska
github
Technischer Redakteur

Enthusiast für Softwareentwicklung mit 9 Jahren Berufserfahrung in dieser Branche.

Bianka Pluszczewska
github
Technischer Redakteur

Enthusiast für Softwareentwicklung mit 9 Jahren Berufserfahrung in dieser Branche.

Read next

No items found...