Es gibt wahrscheinlich keine perfekten Technologien. Graphql ist keine Ausnahme. Wenn Sie noch keine Erfahrung mit dieser Technologie haben, müssen Sie eine gute Vorstellung davon haben, welche Probleme Sie möglicherweise haben, und sich im Voraus darauf vorbereiten.
Zunächst möchte ich sagen, dass ich eher ein Unterstützer als ein Gegner der Verwendung von graphql bin, wenn dies möglich ist. Und ich werde niemanden davon abhalten, diese Technologie angemessen einzusetzen. Und deshalb stelle ich Fragen, die sich auf ungelöste Probleme im Rahmen der Graphql-Technologie beziehen.
Beispielsweise kann es für jemanden unerwartet sein, dass jedes Objekt in graphql mindestens zweimal beschrieben werden muss: einmal als Rückgabetyp des Objekts und noch einmal als Eingabetyp des Objekts (siehe
graphql.org/graphql-js/mutations- und-Eingabetypen ). Ich habe dies jedoch zunächst gesagt und halte es nicht einmal für einen wesentlichen Nachteil. Heute konzentrieren wir uns auf solche Probleme, die in der Regel bei der Entwicklung einer Anwendung mit Graphql-Technologie gelöst werden müssen:
- Trennung des Zugriffs für Benutzer und Benutzergruppen.
- Fehlerbehandlung.
- SELECT N + 1 Problem
Trennung des Zugriffs für Benutzer und Benutzergruppen
graphql weiß nichts über das Teilen des Zugriffs zwischen Benutzern und Gruppen. Daher liegt die gesamte Arbeit zum Teilen des Zugriffs in der Verantwortung des Anwendungsentwicklers. Der dritte Parameter übergibt das Anwendungskontextobjekt an die Resolverfunktion. Wenn Sie beispielsweise mit der Implementierung von graphql JavaScript + express arbeiten, können Sie im Kontextparameter den aktuellen Benutzer aus dem Objekt request express.js abrufen. Weitere Arbeiten zur Zugangskontrolle sollten jedoch direkt in jedem Resolver durchgeführt werden:
function(root, {id}, ctx) { return DB.Lists.get(id) .then( list => { if(list.owner_id && list.owner_id != ctx.userId){ throw new Error("Not authorized to see this list"); } else { return list; } }); }
Natürlich erschwert dieser Ansatz die Zugangskontrolle, weil Es gibt keine Möglichkeit, Zugriffsrechte deklarativ festzulegen, und die Kontrolle über Rechte ist auf Dutzende (bei einigen großen Systemen über Tausende) von Resolverfunktionen verteilt. Daher gibt es eine Reihe von Bibliotheken, die dieses Problem lösen. Einige von ihnen sind sehr beliebt (gemessen an der Anzahl der Sterne auf github.com), zum Beispiel
github.com/maticzav/graphql-shield .
Fehlerbehandlung
Wenn Ihr Frontend eine Eingabevalidierung und die Generierung detaillierter Nachrichten für jedes Feld erfordert, das die Validierung nicht bestanden hat, erscheint Ihnen die Fehlerbehandlung in graphql höchstwahrscheinlich nicht flexibel genug. Wenn der Eingabeparameter beispielsweise als Zeichenfolge beschrieben wurde und ein numerischer Wert empfangen wurde, ist die Fehlermeldung hierfür von geringem Nutzen:
{ "errors": [ { "message": "Expected type String, found 1.", "locations": [ { "line": 2, "column": 15 } ] } ] }
Wenn bei der Art des Eingabeparameters ein schwerwiegender Fehler vorliegt, wird automatisch eine Fehlermeldung generiert, und es gibt keine Möglichkeit, diesen Prozess zu steuern. Wenn die Validierung nach Typ des Eingabeparameters erfolgreich war, kann eine benutzerdefinierte Fehlermeldung an den Client gesendet werden, indem ein
new Error ('custom message ...')
. Es funktioniert nicht, dem Fehlerobjekt benutzerdefinierte Felder hinzuzufügen (die Fehleranpassung wird in den Bibliotheken Apollo-Server-Express und Apollo-Fehler implementiert, wenn sie zusammen verwendet werden). Natürlich besteht immer die Möglichkeit, das Objekt in eine
message
auf dem Server zu serialisieren und auf dem Client zu deserialisieren. Aber ist das notwendig?
SELECT N + 1 Problem
Dieses Problem wurde in der Nachricht ausführlich besprochen .
graphql basiert auf Resolver-Funktionen. Dies bedeutet, dass das Abrufen von Daten aus der Datenbank ein Problem namens SELECT N + 1 verursachen kann. Angenommen, in der Resolver-Funktion wurde eine Liste von Objekten erhalten, in der die diesem Objekt zugeordneten Daten durch Bezeichner (Fremdschlüssel) dargestellt werden. Für jede solche Kennung wird ein eigener Funktionsauflöser aufgerufen, in dem (jeweils) eine zusätzliche Anforderung an die Datenbank gestellt wird. Daher werden anstelle einer einzelnen Datenbankabfrage (mit SQL JOIN) viele Abfragen ausgeführt, wodurch die Datenbank mit Abfragen überlastet wird.
Um dieses Problem zu lösen, hat Facebook die Bibliothek
github.com/graphql/dataloader entwickelt, die eine Strategie für ausstehende Anforderungen verwendet. Anstatt die Anforderung direkt im Funktionsauflöser auszuführen, wird vorgeschlagen, Bezeichner (Sekundärschlüssel) im Array zu akkumulieren und sie dann sofort mit einer Anforderung zu empfangen.
apapacy@gmail.com
13. Mai 2019