GraphQL - szybki przewodnik
GraphQL to technologia open source po stronie serwera, która została opracowana przez Facebooka w celu optymalizacji wywołań RESTful API. Jest to silnik wykonawczy i język zapytań o dane. W tym rozdziale omówimy zalety korzystania z GraphQL.
Dlaczego GraphQL
RESTful API są zgodne z przejrzystym i dobrze zorganizowanym podejściem zorientowanym na zasoby. Jednak gdy dane stają się bardziej złożone, trasy stają się dłuższe. Czasami nie jest możliwe pobranie danych za pomocą jednego żądania. Tutaj przydaje się GraphQL. GraphQL strukturyzuje dane w postaci wykresu z potężną składnią zapytań do przechodzenia, pobierania i modyfikowania danych.
Oto zalety używania języka zapytań GraphQL -
Zapytaj o co chcesz - i zdobądź to
Wyślij zapytanie GraphQL do swojego API i uzyskaj dokładnie to, czego potrzebujesz. Zapytania GraphQL zawsze zwracają przewidywalne wyniki. Aplikacje korzystające z GraphQL są szybkie i stabilne. W przeciwieństwie do usług Restful, aplikacje te mogą ograniczać dane, które powinny być pobierane z serwera.
Poniższy przykład pomoże ci lepiej to zrozumieć -
Rozważmy obiekt biznesowy Student z atrybutami id, firstName, lastName i collegeName . Załóżmy, że aplikacja mobilna musi pobierać tylko imię i nazwisko oraz identyfikator . Jeśli zaprojektujemy punkt końcowy REST, taki jak / api / v1 / Students , zakończy się pobieranie danych dla wszystkich pól dla obiektu studenta . Oznacza to, że usługa RESTful pobiera za dużo danych. Ten problem można rozwiązać za pomocą GraphQL.
Rozważ zapytanie GraphQL podane poniżej -
{
students {
id
firstName
}
}
To zwróci wartości tylko dla pól id i imię. Zapytanie nie pobierze wartości dla innych atrybutów obiektu ucznia. Odpowiedź na zapytanie przedstawione powyżej jest taka, jak pokazano poniżej -
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim"
},
{
"id": "S1002",
"firstName": "Kannan"
}
]
}
}
Uzyskaj wiele zasobów w jednym żądaniu
Zapytania GraphQL pomagają płynnie pobierać powiązane obiekty biznesowe, podczas gdy typowe interfejsy API REST wymagają ładowania z wielu adresów URL. Interfejsy GraphQL pobierają wszystkie dane potrzebne aplikacji w jednym żądaniu. Aplikacje korzystające z GraphQL mogą być szybkie nawet przy wolnych połączeniach z siecią komórkową.
Rozważmy jeszcze jeden obiekt biznesowy, College, który ma atrybuty: nazwę i lokalizację. Obiekt biznesowy Student jest powiązany z obiektem College. Gdybyśmy mieli użyć REST API w celu pobrania danych studentów i ich uczelni, w końcu wyślemy dwa żądania do serwera, takie jak / api / v1 / Students i / api / v1 / colleges . Doprowadzi to do niedostatecznego pobierania danych przy każdym żądaniu. Dlatego aplikacje mobilne są zmuszone do wykonywania wielu połączeń z serwerem w celu uzyskania żądanych danych.
Jednak aplikacja mobilna może pobierać szczegóły zarówno dla obiektów studenta, jak i uczelni w jednym żądaniu przy użyciu GraphQL.
Poniżej znajduje się zapytanie GraphQL do pobrania danych -
{
students{
id
firstName
lastName
college{
name
location
}
}
}
Wynik powyższego zapytania zawiera dokładnie te pola, o które prosiliśmy, jak pokazano poniżej -
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim",
"lastName": "Mohammad",
"college": {
"name": "CUSAT",
"location": "Kerala"
}
},
{
"id": "S1002",
"firstName": "Kannan",
"lastName": "Sudhakaran",
"college": {
"name": "AMU",
"location": "Uttar Pradesh"
}
},
{
"id": "S1003",
"firstName": "Kiran",
"lastName": "Panigrahi",
"college": {
"name": "AMU",
"location": "Uttar Pradesh"
}
}
]
}
}
Opisz, co jest możliwe w systemie typów
GraphQL jest silnie wpisany, a zapytania są oparte na polach i skojarzonych z nimi typach danych. Jeśli w zapytaniu GraphQL wystąpi niezgodność typów, aplikacje serwera zwracają jasne i pomocne komunikaty o błędach. Pomaga to w płynnym debugowaniu i łatwym wykrywaniu błędów przez aplikacje klienckie. GraphQL udostępnia również biblioteki po stronie klienta, które mogą pomóc w zmniejszeniu jawnej konwersji i analizy danych.
Poniżej podano przykład typów danych dla studentów i uczelni -
type Query {
students:[Student]
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
college:College
}
type College {
id:ID!
name:String
location:String
rating:Float
students:[Student]
}
Działaj szybciej dzięki potężnym narzędziom programistycznym
GraphQL zapewnia bogate narzędzia programistyczne do tworzenia dokumentacji i zapytań testowych. GraphiQL to doskonałe narzędzie do tworzenia dokumentacji zapytania i jego schematu. Udostępnia również edytor zapytań do testowania interfejsów API GraphQL i inteligentnego uzupełniania kodu podczas tworzenia zapytań.
W tym rozdziale dowiemy się o konfiguracji środowiska dla GraphQL. Aby wykonać przykłady w tym samouczku, będziesz potrzebować:
Komputer z systemem Linux, macOS lub Windows.
Przeglądarka internetowa, najlepiej najnowsza wersja Google Chrome.
Zainstalowano najnowszą wersję Node.js. Zalecana jest najnowsza wersja LTS.
Visual Studio Code z zainstalowanym rozszerzeniem GraphQL for VSCode lub dowolnym wybranym edytorem kodu.
Jak zbudować serwer GraphQL za pomocą Nodejs
Przejdziemy przez szczegółowe, krokowe podejście do budowy serwera GraphQL z Nodejs, jak pokazano poniżej -
Krok 1 - Sprawdź wersje Node i Npm
Po zainstalowaniu NodeJs sprawdź wersję node i npm używając następujących poleceń na terminalu -
C:\Users\Admin>node -v
v8.11.3
C:\Users\Admin>npm -v
5.6.0
Krok 2 - Utwórz folder projektu i otwórz w VSCode
Folder główny projektu można nazwać jako test-app.
Otwórz folder za pomocą edytora kodu Visual Studio, postępując zgodnie z poniższymi instrukcjami -
C:\Users\Admin>mkdir test-app
C:\Users\Admin>cd test-app
C:\Users\Admin\test-app>code.
Krok 3 - Utwórz plik package.json i zainstaluj zależności
Utwórz plik package.json, który będzie zawierał wszystkie zależności aplikacji serwerowej GraphQL.
{
"name": "hello-world-server",
"private": true,
"scripts": {
"start": "nodemon --ignore data/ server.js"
},
"dependencies": {
"apollo-server-express": "^1.4.0",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"graphql": "^0.13.2",
"graphql-tools": "^3.1.1"
},
"devDependencies": {
"nodemon": "1.17.1"
}
}
Zainstaluj zależności, używając polecenia podanego poniżej -
C:\Users\Admin\test-app>npm install
Krok 4 - Utwórz bazę danych plików płaskich w folderze danych
Na tym etapie do przechowywania i pobierania danych używamy plików płaskich. Utwórz dane folderu i dodaj dwa plikistudents.json i colleges.json.
Poniżej znajduje się colleges.json plik -
[
{
"id": "col-101",
"name": "AMU",
"location": "Uttar Pradesh",
"rating":5.0
},
{
"id": "col-102",
"name": "CUSAT",
"location": "Kerala",
"rating":4.5
}
]
Poniżej znajduje się students.json plik -
[
{
"id": "S1001",
"firstName":"Mohtashim",
"lastName":"Mohammad",
"email": "[email protected]",
"password": "pass123",
"collegeId": "col-102"
},
{
"id": "S1002",
"email": "[email protected]",
"firstName":"Kannan",
"lastName":"Sudhakaran",
"password": "pass123",
"collegeId": "col-101"
},
{
"id": "S1003",
"email": "[email protected]",
"firstName":"Kiran",
"lastName":"Panigrahi",
"password": "pass123",
"collegeId": "col-101"
}
]
Krok 5 - Utwórz warstwę dostępu do danych
Musimy utworzyć magazyn danych, który ładuje zawartość folderu danych. W tym przypadku potrzebujemy zmiennych kolekcji, studentów i uczelni . Gdy aplikacja potrzebuje danych, korzysta z tych zmiennych kolekcji.
Utwórz plik db.js w folderze projektu w następujący sposób -
const { DataStore } = require('notarealdb');
const store = new DataStore('./data');
module.exports = {
students:store.collection('students'),
colleges:store.collection('colleges')
};
Krok 6 - Utwórz plik schematu, schema.graphql
Utwórz plik schematu w bieżącym folderze projektu i dodaj następującą zawartość -
type Query {
test: String
}
Krok 7 - Utwórz plik resolvera, resolvers.js
Utwórz plik resolvera w bieżącym folderze projektu i dodaj następującą zawartość -
const Query = {
test: () => 'Test Success, GraphQL server is up & running !!'
}
module.exports = {Query}
Krok 8 - Utwórz Server.js i skonfiguruj GraphQL
Utwórz plik serwera i skonfiguruj GraphQL w następujący sposób -
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const db = require('./db');
const port = process.env.PORT || 9000;
const app = express();
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})
app.use(cors(), bodyParser.json());
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
app.listen(
port, () => console.info(
`Server started on port ${port}`
)
);
Krok 9 - Uruchom aplikację i przetestuj z GraphiQL
Sprawdź strukturę folderów aplikacji testowej projektu w następujący sposób -
test-app /
-->package.json
-->db.js
-->data
students.json
colleges.json
-->resolvers.js
-->schema.graphql
-->server.js
Uruchom polecenie npm start, jak podano poniżej -
C:\Users\Admin\test-app>npm start
Serwer działa na porcie 9000, więc możemy przetestować aplikację za pomocą narzędzia GraphiQL. Otwórz przeglądarkę i wprowadź adres URL http: // localhost: 9000 / graphiql. Wpisz następujące zapytanie w edytorze -
{
Test
}
Odpowiedź z serwera jest podana poniżej -
{
"data": {
"test": "Test Success, GraphQL server is running !!"
}
}
GraphQL to specyfikacja opisująca zachowanie serwera GraphQL. Jest to zbiór wskazówek dotyczących obsługi żądań i odpowiedzi, takich jak obsługiwane protokoły, format danych, które mogą być akceptowane przez serwer, format odpowiedzi zwracanej przez serwer itp. Żądanie wysłane przez klienta do GraphQL serwer nazywa się Query. Inną ważną koncepcją GraphQL jest agnostyka warstwy transportowej. Może być używany z dowolnym dostępnym protokołem sieciowym, takim jak TCP, websocket lub dowolnym innym protokołem warstwy transportowej. Jest również neutralny dla baz danych, więc można go używać z bazami relacyjnymi lub NoSQL.
GraphQL Server można wdrożyć za pomocą jednej z trzech metod wymienionych poniżej -
- Serwer GraphQL z podłączoną bazą danych
- Serwer GraphQL integrujący istniejące systemy
- Podejście hybrydowe
GraphQL Server z podłączoną bazą danych
Ta architektura ma serwer GraphQL ze zintegrowaną bazą danych i często może być używana w nowych projektach. Po otrzymaniu zapytania serwer odczytuje ładunek żądania i pobiera dane z bazy danych. Nazywa się to rozwiązywaniem zapytania. Odpowiedź zwrócona klientowi jest zgodna z formatem określonym w oficjalnej specyfikacji GraphQL.
Na powyższym schemacie serwer GraphQL i baza danych są zintegrowane w jednym węźle. Klient (stacjonarny / mobilny) komunikuje się z serwerem GraphQL przez HTTP. Serwer przetwarza żądanie, pobiera dane z bazy danych i zwraca je do klienta.
GraphQL Server integrujący istniejące systemy
Takie podejście jest przydatne dla firm, które mają starszą infrastrukturę i różne interfejsy API. GraphQL może służyć do ujednolicenia mikrousług, starszej infrastruktury i zewnętrznych interfejsów API w istniejącym systemie.
Na powyższym diagramie GraphQL API działa jako interfejs między klientem a istniejącymi systemami. Aplikacje klienckie komunikują się z serwerem GraphQL, który z kolei rozwiązuje zapytanie.
Podejście hybrydowe
Wreszcie możemy połączyć powyższe dwa podejścia i zbudować serwer GraphQL. W tej architekturze serwer GraphQL rozwiąże każde otrzymane żądanie. Pobierze dane z podłączonej bazy danych lub ze zintegrowanych interfejsów API. Przedstawia to poniższy rysunek -
W tym rozdziale omówiono różne komponenty GraphQL i sposób, w jaki się ze sobą komunikują. Całość komponentów aplikacji można wyróżnić jak poniżej -
- Komponenty po stronie serwera
- Komponenty po stronie klienta
Składniki po stronie serwera
Serwer GraphQL stanowi podstawowy komponent po stronie serwera i umożliwia analizowanie zapytań pochodzących z aplikacji klienckich GraphQL. Apollo Server to najczęściej stosowana implementacja specyfikacji GraphQL. Inne komponenty programowania serwera obejmują:
Sr.No. | Podstawowe informacje i opis serwera |
---|---|
1 | Schema Schemat GraphQL znajduje się w centrum każdej implementacji serwera GraphQL i opisuje funkcje dostępne dla klientów, którzy się z nim łączą. |
2 | Query Zapytanie GraphQL to żądanie aplikacji klienckiej w celu pobrania danych z bazy danych lub starszych interfejsów API. |
3 | Resolver Resolwery udostępniają instrukcje dotyczące zamiany operacji GraphQL na dane. Przekształcają zapytanie na dane, definiując funkcje przelicznika. |
Komponenty po stronie klienta
Poniżej podano komponenty po stronie klienta -
Sr.No. | Narzędzie i opis |
---|---|
1 | GraphiQL Oparty na przeglądarce interfejs do edycji i testowania zapytań i mutacji GraphQL. |
2 | ApolloClient Najlepsze narzędzie do tworzenia aplikacji klienckich GraphQL. Dobrze integruje się ze wszystkimi front-endami javascript. |
Poniższy diagram przedstawia Client-Server architecture. Serwer WWW jest zbudowany na frameworku NodeJs i Express. Żądanie jest wysyłane do serwera Apollo GraphQL przez aplikację ReactJS (zbudowaną przy użyciu biblioteki Apollo Client) lub aplikację przeglądarki GraphiQL. Zapytanie zostanie przeanalizowane i sprawdzone pod kątem schematu zdefiniowanego na serwerze. Jeśli schemat żądania przejdzie walidację, zostaną wykonane powiązane funkcje przelicznika. Program rozpoznawania nazw będzie zawierał kod do pobierania danych z interfejsu API lub bazy danych.
W tym rozdziale utworzymy proste API, które zwraca wiadomość powitalną HelloWorld i uzyskuje do niego dostęp za pomocą GraphiQL.
Przykład
Ten przykład jest oparty na serwerze NodeJS, Express i Apollo. Nauczymy się łączyć wszystkie koncepcje w następujące kroki -
Krok 1 - Konfiguracja Express
ExpressJS to platforma aplikacji internetowych, która pomaga w tworzeniu witryn i aplikacji internetowych. W tym przykładzie utworzymy interfejs API GraphQL na podstawie struktury Express.
Następnym krokiem jest utworzenie folderu hello-world-serveri przejdź do tego samego folderu z terminala. Dodaj package.json i nadaj nazwę pakietowi. Ponieważ ten pakiet jest używany tylko wewnętrznie, możemy zadeklarować go jako prywatny.
{
"name":"hello-world-server",
"private":true
}
Zainstaluj zależności dla serwera Express, jak pokazano poniżej -
C:\Users\Admin\hello-world-server>npm install express body-parser cors
body-parser to pakiet oprogramowania pośredniego, który pomaga Expressowi efektywnie obsługiwać żądania HTTP Post. cors to kolejny pakiet oprogramowania pośredniego, który obsługuje udostępnianie zasobów między źródłami.
Stwórz server.js plik w folderze projektu i wpisz w nim:
const bodyParser = require('body-parser')
const cors = require('cors')
const express = require('express')
const port = process.env.PORT|| 9000
const app = express()
//register middleware
app.use(bodyParser.json() , cors())
app.listen(port, () => console.log(`server is up and running at ${port}`)
Aby sprawdzić, czy serwer Express działa i działa, wykonaj następujący kod w oknie terminala -
C:\Users\Admin\hello-world-server>node server.js
Następujące dane wyjściowe są wyświetlane w konsoli serwera. To pokazuje, że serwer ekspresowy działa na porcie 9000.
server is up and running at 9000
Jeśli otworzysz przeglądarkę i wpiszesz http://localhost:9000, pojawi się następujący ekran -
Aby zatrzymać serwer, naciśnij Ctrl + C.
Krok 2 - Zainstaluj GraphQL i Apollo Server
Teraz, gdy Express jest skonfigurowany, następnym krokiem jest pobranie następujących zależności GraphQL -
- graphql
- graphql-tools
- apollo-server-express@1
Będziemy używać serwera Apollo v1.0, ponieważ jest to wersja stabilna. Wpisz następujące polecenia, aby zainstalować te zależności -
C:\Users\Admin\hello-world-server>npm install graphql graphql-tools apollo-server-express@1
Możemy sprawdzić, czy te zależności zostały pomyślnie zainstalowane, sprawdzając plik package.json plik, który utworzyliśmy wcześniej.
{
"name": "hello-world-server",
"private": true,
"dependencies": {
"apollo-server-express": "^1.4.0",
"body-parser": "^1.18.3",
"cors": "^2.8.4",
"express": "^4.16.3",
"graphql": "^0.13.2",
"graphql-tools": "^3.1.1"
}
}
Krok 3 - Zdefiniuj schemat
Schemat GraphQL definiuje, jaki rodzaj obiektu można pobrać z usługi i jakie pola ma. Schemat można zdefiniować za pomocąGraphQL Schema Definition Language. Teraz dodaj następujący fragment kodu wserver.js plik -
// Adding Type Definitions
const typeDefinition = `
type Query {
greeting: String
}
W tym przypadku zapytanie zawiera atrybut powitania, który zwraca wartość ciągu .
Krok 4 - Utwórz resolver
Pierwszym krokiem w tworzeniu resolwera jest dodanie kodu przetwarzającego żądanie powitania. Jest to określone wresolver. Struktura funkcji przelicznika musi być zgodna ze schematem. Dodaj następujący fragment kodu wserver.js plik.
// Adding resolver
const resolverObject = {
Query : {
greeting: () => 'Hello GraphQL From TutorialsPoint !!'
}
}
Drugim krokiem jest powiązanie schematu i programu rozpoznawania nazw za pomocą makeExecutableSchema. Ta funkcja jest wstępnie zdefiniowana w module graphql-tools. Dodaj następujący fragment kodu w server.js plik.
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs:typeDefinition, resolvers:resolverObject})
Krok 5 - Zdefiniuj procedury pobierania danych z aplikacji ReactJS / GraphiQL
Dodaj następujący fragment kodu w server.js plik -
const {graphqlExpress, graphiqlExpress} = require('apollo-server-express')
//create routes for graphql and graphiql
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
Funkcja graphqlExpress pomaga zarejestrować trasęhttp://localhost:9000/graphql. Aplikacja ReactJS może używać tego punktu końcowego do wykonywania zapytań dotyczących danych. Podobnie funkcja graphqliExpress pomaga zarejestrować trasęhttp://localhost:9000/graphiql. Będzie to używane przez klienta przeglądarki GraphiQL do testowania interfejsu API.
Pełny kod server.js jest podany poniżej -
const bodyParser = require('body-parser')
const cors = require('cors')
const express = require('express')
const port = process.env.PORT||9000
const app = express()
app.use(bodyParser.json() , cors())
const typeDefinition = `
type Query {
greeting: String
}`
const resolverObject = {
Query : {
greeting: () => 'Hello GraphQL From TutorialsPoint !!'
}
}
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs:typeDefinition, resolvers:resolverObject})
const {graphqlExpress,graphiqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
app.listen(port, () => console.log(`server is up and running ${port}`))
Krok 6 - Uruchom aplikację
Wykonać server.js używając Node.js w następujący sposób -
C:\Users\Admin\hello-world-server>node server.js
Krok 7 - Przetestuj GraphQL API
Otwórz przeglądarkę i wpisz http://localhost:9000/graphiql. Na karcie zapytania GraphiQL wprowadź następujące dane -
{
greeting
}
Odpowiedź z serwera jest podana poniżej -
{
"data": {
"greeting": "Hello GraphQL From TutorialsPoint !!"
}
}
Poniższy obraz ilustruje odpowiedź -
Note - Upewnij się, że używany jest serwer Apollo w wersji 1.0.
GraphQL jest językiem silnie typizowanym. Type System definiuje różne typy danych, które mogą być używane w aplikacji GraphQL. System typów pomaga zdefiniować schemat, który jest kontraktem między klientem a serwerem. Powszechnie używane typy danych GraphQL są następujące -
Sr.No. | Rodzaje i opis |
---|---|
1 | Scalar Przechowuje pojedynczą wartość |
2 | Object Pokazuje, jaki rodzaj obiektu można pobrać |
3 | Query Typ punktu wejścia do innych określonych typów |
4 | Mutation Punkt wejścia do manipulacji danymi |
5 | Enum Przydatne w sytuacji, gdy potrzebujesz, aby użytkownik wybrał z określonej listy opcji |
Typ skalarny
Typy skalarne to prymitywne typy danych, które mogą przechowywać tylko jedną wartość. Domyślne typy skalarne oferowane przez GraphQL to -
Int - Podpisana 32-bitowa liczba całkowita
Float - Podpisana wartość zmiennoprzecinkowa podwójnej precyzji
String - UTF - sekwencja 8 znaków
Boolean - Prawda czy fałsz
ID - Unikalny identyfikator, często używany jako unikalny identyfikator do pobierania obiektu lub jako klucz do pamięci podręcznej.
Składnia definiowania typu skalarnego jest następująca -
field: data_type
Podany poniżej fragment definiuje pole o nazwie greeting, które zwraca wartość String.
greeting: String
Rodzaj obiektu
Typ obiektu jest typem najczęściej używanym w schemacie i reprezentuje grupę pól. Każde pole wewnątrz typu obiektu jest mapowane na inny typ, umożliwiając w ten sposób zagnieżdżone typy. Innymi słowy, typ obiektowy składa się z wielu typów skalarnych lub typów obiektów.
Składnia do definiowania typu obiektu jest podana poniżej -
type object_type_name
{
field1: data_type
field2:data_type
....
fieldn:data_type
}
Możesz rozważyć następujący fragment kodu -
--Define an object type--
type Student {
stud_id:ID
firstname: String
age: Int
score:Float
}
--Defining a GraphQL schema--
type Query
{
stud_details:[Student]
}
Podany powyżej przykład definiuje obiekt typu danych Student. Pole stud_details w głównym schemacie zapytań zwróci listę obiektów Studentów.
Typ zapytania
Zapytanie GraphQL służy do pobierania danych. To jest jak żądanie zasobu w interfejsach API opartych na REST. Aby to uprościć, typ zapytania to żądanie wysłane z aplikacji klienckiej do serwera GraphQL. GraphQL używaSchema Definition Language (SDL)aby zdefiniować zapytanie. Typ zapytania jest jednym z wielu typów poziomu głównego w GraphQL.
Składnia definiowania zapytania jest następująca:
type Query {
field1: data_type
field2:data_type
field2(param1:data_type,param2:data_type,...paramN:data_type):data_type
}
Przykład definiowania zapytania -
type Query {
greeting: String
}
Typ mutacji
Mutacje to operacje wysyłane do serwera create, update lub deletedane. Są one analogiczne do czasowników PUT, POST, PATCH i DELETE, które wywołują interfejsy API oparte na REST.
Mutacja jest jednym z głównych typów danych w GraphQL. Typ Query definiuje punkty wejścia dla operacji pobierania danych, podczas gdy typ Mutation określa punkty wejścia dla operacji manipulacji danymi.
Składnia definiowania typu mutacji jest podana poniżej -
type Mutation {
field1: data_type
field2(param1:data_type,param2:data_type,...paramN:data_type):data_type
}
Na przykład możemy zdefiniować typ mutacji, aby dodać nowego Studenta, jak poniżej -
type Mutation {
addStudent(firstName: String, lastName: String): Student
}
Typ wyliczenia
Enum jest podobne do typu skalarnego. Wyliczenia są przydatne w sytuacji, gdy wartość pola musi pochodzić z określonej listy opcji.
Składnia definiowania typu wyliczenia to -
type enum_name{
value1
value2
}
Poniższy fragment ilustruje, jak można zdefiniować typ wyliczenia -
type Days_of_Week{
SUNDAY
MONDAY
TUESDAY
WEDNESDAY
THURSDAY
FRIDAY
SATURDAY
}
Typ listy
Listy mogą służyć do reprezentowania tablicy wartości określonego typu. Listy są definiowane za pomocą modyfikatora typu [], który otacza typy obiektów, skalary i wyliczenia.
Do zdefiniowania typu listy można użyć następującej składni -
field:[data_type]
Poniższy przykład definiuje listę rzeczy do zrobienia -
type Query {
todos: [String]
}
Typ niezawierający wartości null
Domyślnie każdy z podstawowych typów skalarnych może mieć wartość null. Innymi słowy, te typy mogą zwracać wartość określonego typu lub mogą nie mieć żadnej wartości. Aby zastąpić to ustawienie domyślne i określić, że pole musi być zdefiniowane, do typu można dołączyć wykrzyknik (!). Zapewnia to obecność wartości w wynikach zwracanych przez zapytanie.
Poniższa składnia może służyć do definiowania pola niedopuszczającego wartości null -
field:data_type!
W poniższym przykładzie stud_id jest zadeklarowane jako pole obowiązkowe.
type Student {
stud_id:ID!
firstName:String
lastName:String
fullName:String
college:College
}
Schemat GraphQL jest podstawą każdej implementacji serwera GraphQL. Opisuje funkcje dostępne dla aplikacji klienckich, które się z nim łączą. Możemy użyć dowolnego języka programowania, aby stworzyć schemat GraphQL i zbudować wokół niego interfejs.
Środowisko uruchomieniowe GraphQL definiuje ogólny schemat oparty na wykresie do publikowania możliwości usługi danych, którą reprezentuje. Aplikacje klienckie mogą wysyłać zapytania do schematu w ramach swoich możliwości. Takie podejście oddziela klientów od serwerów i umożliwia niezależne rozwijanie i skalowanie.
W tym rozdziale używamy serwera Apollo do wykonywania zapytań GraphQL. PlikmakeExecutableSchema funkcja w graphql-tools pomaga w powiązaniu schematu i resolwerów.
Składnia funkcji makeExecutableSchema
Plik makeExecutableSchemafunkcja przyjmuje pojedynczy argument {} typu Object. Składnia użycia tej funkcji jest podana poniżej -
import { makeExecutableSchema } from 'graphql-tools';
const jsSchema = makeExecutableSchema({
typeDefs,
resolvers, // optional
logger, // optional
allowUndefinedInResolve = false, // optional
resolverValidationOptions = {}, // optional
directiveResolvers = null, // optional
schemaDirectives = null, // optional
parseOptions = {}, // optional
inheritResolversFromInterfaces = false // optional
});
Sr.No. | Parametr i opis |
---|---|
1 | typeDefs To jest wymagany argument. Reprezentuje zapytanie GraphQL jako ciąg znaków UTF-8. |
2 | Resolvers To jest argument opcjonalny (domyślnie pusty obiekt). Zawiera funkcje obsługujące zapytanie. |
3 | logger Jest to argument opcjonalny i może służyć do drukowania błędów na konsoli serwera. |
4 | parseOptions Jest to argument opcjonalny i umożliwia dostosowanie analizy składniowej podczas określania typeDefs jako ciągu. |
5 | allowUndefinedInResolve Tak jest domyślnie. Ustawienie wartości false powoduje, że funkcje rozpoznawania zwracają błędy, jeśli zwracają wartość undefined. |
6 | resolverValidationOptions To jest argument opcjonalny i akceptuje obiekt z właściwościami logicznymi. |
7 | inheritResolversFromInterfaces Jest to argument opcjonalny i akceptuje argument logiczny w celu sprawdzenia dziedziczenia obiektów mechanizmu rozpoznawania nazw. |
Ilustracja
Stwórzmy prostą aplikację, aby zrozumieć ten schemat. Spowoduje to utworzenie schematu odpytywania listy uczniów z serwera. Dane studenta zostaną zapisane w płaskim pliku i użyjemy modułu węzła o nazwienotarealdb sfałszować bazę danych i czytać z pliku płaskiego.
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder o nazwie schema-app. Zmień katalog na aplikację schematu z poziomu terminala. Następnie wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska, aby zakończyć pobieranie i proces instalacji.
Krok 2 - Utwórz schemat
Dodaj schema.graphql plik w folderze projektu, schema-app i dodaj następujący kod -
type Query {
greeting:String
students:[Student]
}
type Student {
id:ID!
firstName:String
lastName:String
password:String
collegeId:String
}
Katalog główny schematu będzie typu Query. Zapytanie ma dwa pola - powitanie i Studenci, które zwraca odpowiednio ciąg znaków i listę uczniów. Student jest zadeklarowany jako typ obiektu, ponieważ zawiera wiele pól. Pole ID jest zadeklarowane jako nie dopuszcza wartości null.
Krok 3 - Utwórz resolver
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const db = require('./db')
const Query = {
greeting:() => {
return "hello from TutorialsPoint !!!"
},
students:() => db.students.list()
}
module.exports = {Query}
Tutaj powitanie i uczniowie są osobami tłumaczącymi, które obsługują zapytanie. students resolver functionzwraca listę studentów z warstwy dostępu do danych. Aby uzyskać dostęp do funkcji przelicznika poza modułem, obiekt Query należy wyeksportować za pomocąmodule.exports.
Krok 4 - Uruchom aplikację
Utwórz plik server.js i zapoznaj się z krokiem 8 w rozdziale Konfiguracja środowiska. Następnym krokiem jest wykonanie polecenia npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji. Otwórz przeglądarkę i wpisz adres URL,http://localhost:9000/graphiql.
Wpisz następujące zapytanie w edytorze -
{
greeting
students {
id
firstName
lastName
}
}
Zapytanie wyświetli dane wyjściowe, jak pokazano poniżej -
Note- Możemy zastąpić plik Students.json wywołaniem RESTful API w celu pobrania danych uczniów lub nawet prawdziwej bazy danych, takiej jak MySQL lub MongoDB. GraphQL staje się cienkim opakowaniem wokół oryginalnej warstwy aplikacji, aby poprawić wydajność.
Resolver to zbiór funkcji, które generują odpowiedź na zapytanie GraphQL. Mówiąc prościej, przelicznik działa jako program obsługi zapytań GraphQL. Każda funkcja przelicznika w schemacie GraphQL akceptuje cztery argumenty pozycyjne, jak podano poniżej -
fieldName:(root, args, context, info) => { result }
Przykład funkcji przelicznika pokazano poniżej -
//resolver function with no parameters and returning string
greeting:() => {
return "hello from TutorialsPoint !!!"
}
//resolver function with no parameters and returning list
students:() => db.students.list()
//resolver function with arguments and returning object
studentById:(root,args,context,info) => {
return db.students.get(args.id);
}
Poniżej podano argumenty pozycyjne i ich opis -
Sr.No. | Argumenty i opis |
---|---|
1 | root Obiekt zawierający wynik zwrócony przez program rozpoznawania nazw w polu nadrzędnym. |
2 | args Obiekt z argumentami przekazanymi do pola w zapytaniu. |
3 | context Jest to obiekt współdzielony przez wszystkie resolwery w danym zapytaniu. |
4 | info Zawiera informacje o stanie wykonania zapytania, w tym nazwę pola, ścieżkę do pola z katalogu głównego. |
Format wyniku rozpoznawania nazw
Resolwery w GraphQL mogą zwracać różne typy wartości, jak podano poniżej -
Sr.No. | Argumenty i opis |
---|---|
1 | null or undefined oznacza to, że nie można znaleźć obiektu |
2 | array jest to poprawne tylko wtedy, gdy schemat wskazuje, że wynikiem pola powinna być lista |
3 | promise resolwery często wykonują czynności asynchroniczne, takie jak pobieranie z bazy danych lub interfejsu API zaplecza, dzięki czemu mogą zwracać obietnice |
4 | scalar or object przelicznik może również zwracać inne wartości |
Ilustracja
Stwórzmy prostą aplikację do zrozumienia resolvera. Spowoduje to utworzenie schematu do wysyłania zapytań do ucznia na podstawie identyfikatora z serwera. Dane studenta zostaną zapisane w płaskim pliku i użyjemy modułu węzła o nazwienotarealdb sfałszować bazę danych i czytać z pliku płaskiego.
Poniżej przedstawiono etapowy proces tworzenia prostej aplikacji -
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder o nazwie resolver-app. Zmień katalog naresolver-appz terminala. Później wykonaj kroki od 3 do 5 w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
Dodaj plik schema.graphql w aplikacji resolver folderu projektu i dodaj następujący kod -
type Query {
greeting:String
students:[Student]
studentById(id:ID!):Student
}
type Student {
id:ID!
firstName:String
lastName:String
password:String
collegeId:String
}
Plik schematu pokazuje, że użytkownik może zapytać o powitanie, uczniów i studentById . Aby pobrać uczniów z określonym identyfikatorem, używamydata type ID!który pokazuje niepodlegające wartości null pole unikalnego identyfikatora. Pole studentów zwraca tablicę uczniów, a powitanie zwraca prostą wartość ciągu.
Krok 3 - Utwórz resolver
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const db = require('./db')
const Query = {
//resolver function for greeting
greeting:() => {
return "hello from TutorialsPoint !!!"
},
//resolver function for students returns list
students:() => db.students.list(),
//resolver function for studentbyId
studentById:(root,args,context,info) => {
//args will contain parameter passed in query
return db.students.get(args.id);
}
}
module.exports = {Query}
Tutaj studentById przyjmuje trzy parametry. Jak omówiono w tym rozdziale, studentId można pobrać z argumentów; root będzie zawierał sam obiekt Query. Aby zwrócić konkretnego ucznia, musimy wywołać metodę get z parametrem id w kolekcji studentów.
Tutaj pozdrowienia, studenci, studentById to resolwery obsługujące zapytanie.students resolver functionzwraca listę studentów z warstwy dostępu do danych. Aby uzyskać dostęp do funkcji przelicznika poza modułem, obiekt Query musi zostać wyeksportowany za pomocą module.exports.
Krok 4 - Uruchom aplikację
Utwórz plik server.js. Zapoznaj się z krokiem 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji.
Otwórz przeglądarkę i wprowadź adres URL, http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
{
studentById(id:"S1001") {
id
firstName
lastName
}
}
Dane wyjściowe dla powyższego zapytania są pokazane poniżej -
{
"data": {
"studentById": {
"id": "S1001",
"firstName": "Mohtashim",
"lastName": "Mohammad"
}
}
}
Operacja GraphQL może być operacją odczytu lub zapisu. Zapytanie GraphQL służy do odczytywania lub pobierania wartości, podczas gdy mutacja jest używana do zapisywania lub publikowania wartości. W obu przypadkach operacja jest prostym ciągiem, który serwer GraphQL może przeanalizować i na który odpowiedzieć danymi w określonym formacie. Popularnym formatem odpowiedzi, który jest zwykle używany w aplikacjach mobilnych i internetowych, jest JSON.
Składnia definiująca zapytanie jest następująca -
//syntax 1
query query_name{ someField }
//syntax 2
{ someField }
Poniżej znajduje się przykład zapytania -
//query with name myQuery
query myQuery{
greeting
}
// query without any name
{
greeting
}
Z powyższego przykładu jasno wynika, że słowo kluczowe zapytania jest opcjonalne.
Zapytania GraphQL pomagają zredukować nadmierne pobieranie danych. W przeciwieństwie do Restful API, GraphQL umożliwia użytkownikowi ograniczenie pól, które powinny być pobierane z serwera. Oznacza to mniejsze zapytania i mniejszy ruch w sieci; co z kolei skraca czas odpowiedzi.
Ilustracja 1 - Zapytanie o model ucznia z niestandardowym polem
W tym przykładzie mamy zestaw uczniów przechowywany w pliku json. Każdy model ucznia ma takie pola jak firstName, lastName i id, ale nie ma fullName. Tutaj omówimy, jak wykonać zapytanie w celu pobrania pełnej nazwy wszystkich uczniów. W tym celu musimy utworzyć pole fullName w obu programach do rozpoznawania schematów.
Zobaczmy, jak zrobić tę ilustrację, wykonując poniższe czynności -
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder o nazwie query-app. Zmień katalog naquery-appz terminala. Później wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
Dodaj schema.graphql plik w aplikacji zapytania folderu projektu i dodaj następujący kod -
type Query {
greeting:String
students:[Student]
studentById(id:ID!):Student
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}
Zauważ, że nie ma pola fullName wstudents.jsonplik. Musimy jednak pobrać pełne imię i nazwisko ucznia za pomocą zapytania. Fullname , w tym przypadku będzie to niestandardowe pole, które nie jest dostępne w źródle danych.
Krok 3 - Utwórz resolver
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const db = require('./db')
const Query = {
//resolver function for greeting
greeting:() => {
return "hello from TutorialsPoint !!!"
},
//resolver function for students returns list
students:() => db.students.list(),
//resolver function for studentbyId
studentById:(root,args,context,info) => {
//args will contain parameter passed in query
return db.students.get(args.id);
}
}
//for each single student object returned,resolver is invoked
const Student = {
fullName:(root,args,context,info) => {
return root.firstName+":"+root.lastName
}
}
module.exports = {Query,Student}
Krok 4 - Uruchom aplikację
Stwórz server.jsplik. Zobacz krok 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji.
Otwórz przeglądarkę i wpisz adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
{
students{
id
fullName
}
}
Odpowiedź na zapytanie jest podana poniżej -
{
"data": {
"students": [
{
"id": "S1001",
"fullName": "Mohtashim:Mohammad"
},
{
"id": "S1002",
"fullName": "Kannan:Sudhakaran"
},
{
"id": "S1003",
"fullName": "Kiran:Panigrahi"
}
]
}
}
Stwórz server.js i dodaj następujący kod -
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const db = require('./db');
const port = 9000;
const app = express();
//loading type definitions from schema file
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
//loading resolvers
const resolvers = require('./resolvers')
//binding schema and resolver
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})
//enabling cross domain calls and form post
app.use(cors(), bodyParser.json());
//enabling routes
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql',graphqlExpress({schema}))
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
//registering port
app.listen(port, () => console.info(`Server started on port ${port}`));
Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji.
Otwórz przeglądarkę i wpisz adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
{
students{
id
fullName
}
}
Odpowiedź na zapytanie jest podana poniżej -
{
"data": {
"students": [
{
"id": "S1001",
"fullName": "Mohtashim:Mohammad"
},
{
"id": "S1002",
"fullName": "Kannan:Sudhakaran"
},
{
"id": "S1003",
"fullName": "Kiran:Panigrahi"
}
]
}
}
Ilustracja 2 - Zagnieżdżone zapytanie
Utwórzmy zagnieżdżone zapytanie w celu pobrania danych studenta i jego uczelni. Będziemy pracować z tym samym folderem projektu.
Krok 1 - Edytuj schemat
Plik schematu zawiera już pole ucznia . Dodajmy uczelnię terenową i określmy jej typ.
type College {
id:ID!
name:String
location:String
rating:Float
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
college:College
}
Krok 2 - Zmodyfikuj plik resolver.js
Musimy dodać funkcję przelicznika uczelni, jak poniżej. Funkcja rozpoznawania nazw uczelni zostanie wykonana dla każdego zwróconego obiektu studenta. W tym przypadku parametr root resolvera będzie zawierał student .
const Student = {
fullName:(root,args,context,info) => {
return root.firstName+":"+root.lastName
},
college:(root) => {
return db.colleges.get(root.collegeId);
}
}
module.exports = {Query,Student}
Program rozpoznawania nazw zwraca informacje o uczelni każdego ucznia, wywołując metodę pobierania kolekcji uczelni i przekazując identyfikator collegeId . Mamy związek między studentem a kolegium za pośrednictwem collegeId .
Krok 3 - Przetestuj aplikację
Otwórz okno terminala i przejdź do folderu projektu. Wpisz polecenie -npm start. Uruchom przeglądarkę i wprowadź adres URLhttp://localhost:9000/graphiql.
Wprowadź następujące zapytanie w oknie GraphiQL -
{
students{
id
firstName
college {
id
name
location
rating
}
}
}
Odpowiedź na zapytanie jest podana poniżej -
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim",
"college": {
"id": "col-102",
"name": "CUSAT",
"location": "Kerala",
"rating": 4.5
}
},
{
"id": "S1002",
"firstName": "Kannan",
"college": {
"id": "col-101",
"name": "AMU",
"location": "Uttar Pradesh",
"rating": 5
}
},
{
"id": "S1003",
"firstName": "Kiran",
"college": {
"id": "col-101",
"name": "AMU",
"location": "Uttar Pradesh",
"rating": 5
}
}
]
}
}
Co to jest zmienna zapytania?
Jeśli zapytanie ma do przekazania jakieś wartości dynamiczne, przedstaw je za pomocą zmiennych. W związku z tym zapytanie może zostać ponownie wykorzystane przez aplikacje klienckie.
Ilustracja
Stwórzmy prostą aplikację do zrozumienia zmiennej zapytania.
Krok 1 - Edytuj plik schematu
Dodaj pole sayHello, które przyjmuje parametr typu string i zwraca ciąg. Wartości nazw będą dynamiczne w aplikacji klienckiej.
type Query {
sayHello(name:String!):String
}
Krok 2 - Edytuj plik resolver.js
Dodaj resolver sayHello, który przyjmuje parametr jak poniżej -
sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL server says Hello to you!!`
Krok 3 - Zadeklaruj zmienną zapytania w GraphiQL
Zmienna jest deklarowana za pomocą $, po którym następuje nazwa zmiennej. Na przykład: $ myname_Variable.
Po zadeklarowaniu zmiennej $ myname_Variable należy jej użyć z nazwaną składnią zapytania. Zapytanie myQuery przyjmuje wartość ciągu i przekazuje ją do sayHello, jak pokazano poniżej -
query myQuery($myname_Variable:String!) { sayHello(name:$myname_Variable)
}
Ustaw wartość $ myname_Variable jako obiekt JSON w sekcji Query Variables klienta GraphiQL.
{
"myname_Variable": "Mohtashim"
}
Dane wyjściowe powyższego kodu są następujące -
{
"data": {
"sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
}
}
Jak używać zmiennej zapytania z wyliczeniem
Zobaczmy, jak używać zmiennej zapytania, gdy parametr pola to enum type.
Krok 1 - Edytuj plik schema.graphql
enum ColorType {
RED
BLUE
GREEN
}
type Query {
setFavouriteColor(color:ColorType):String
}
Funkcja setFavouriteColor przyjmuje enum jako dane wejściowe i zwraca wartość ciągu.
Krok 2 - Edytuj plik resolvers.js
Funkcja przelicznika setFavouriteColor pobiera root i args . Dostęp do wartości wyliczenia przekazanej do funkcji w czasie wykonywania można uzyskać za pomocą parametru args.
setFavouriteColor:(root,args) => {
return "Your Fav Color is :"+args.color;
}
Krok 3 - Zadeklaruj zmienną zapytania w GraphiQL
Zapytanie nosi nazwę query_to_setColorktóry przyjmuje zmienną o nazwie zmienna_koloru typu ColorType. Ta zmienna jest przekazywana do metody setFavouriteColor.
query query_to_setColor($color_variable:ColorType) {
setFavouriteColor(color:$color_variable)
}
W sekcji zmiennej zapytania programu GraphiQL wpisz następujący kod -
{
"color_variable":"RED"
}
Odpowiedź jest pokazana poniżej -
{
"data": {
"setFavouriteColor": "Your Fav Color is: RED"
}
}
W tym rozdziale nauczymy się zapytań o mutacje w GraphQL.
Zapytania mutacyjne modyfikują dane w składnicy danych i zwracają wartość. Można go używać do wstawiania, aktualizowania lub usuwania danych. Mutacje są definiowane jako część schematu.
Składnia zapytania o mutację jest podana poniżej -
mutation{
someEditOperation(dataField:"valueOfField"):returnType
}
Ilustracja
Pozwól nam zrozumieć, jak dodać nowy rekord ucznia do magazynu danych za pomocą zapytania mutacji.
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder projektu o nazwie mutation-app. Zmień katalog na mutation-app z terminala. Wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz plik schema.graphql
Dodaj schema.graphql plik w folderze projektu mutation-app i dodaj następujący kod -
type Query {
greeting:String
}
type Mutation {
createStudent(collegeId:ID,firstName:String,lastName:String):String
}
Zauważ, że funkcja createStudent zwraca typ String. Jest to unikalny identyfikator (ID), który jest generowany po utworzeniu ucznia.
Krok 3 - Utwórz plik resolver.js
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const db = require('./db')
const Mutation = {
createStudent:(root,args,context,info) => {
return db.students.create({collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName})
}
}
const Query = {
greeting:() => "hello"
}
module.exports = {Query,Mutation}
Funkcja mutacji wskazuje na kolekcję uczniów w magazynie danych. Aby dodać nowego ucznia , wywołaj metodę create w kolekcji uczniów. Obiekt args będzie zawierał parametry przekazane w zapytaniu. Metoda tworzenia kolekcji uczniów zwróci identyfikator nowo utworzonego obiektu studenta.
Krok 4 - Uruchom aplikację
Stwórz server.jsplik. Zobacz krok 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji.
Następnym krokiem jest otwarcie przeglądarki i wpisanie adresu URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
//college Id should be matched with data from colleges.json for easy retrieval
mutation {
createStudent(collegeId:"col-2",firstName:"Tim",lastName:"George")
}
Powyższe zapytanie utworzy obiekt studenta w pliku student.json. Zapytanie zwróci unikalny identyfikator. Odpowiedź na zapytanie jest taka, jak pokazano poniżej -
{
"data": {
"createStudent": "SkQtxYBUm"
}
}
Aby sprawdzić, czy obiekt studenta został utworzony, możemy użyć zapytania studentById. Możesz także otworzyć plik Students.json z folderu danych, aby zweryfikować identyfikator.
Aby użyć zapytania studentById, edytuj plik schema.graphql jak podano poniżej -
type Query {
studentById(id:ID!):Student
}
type Student {
id:ID!
firstName:String
lastName:String
collegeId:String
}
Edytuj plik resolver.js plik jak podano poniżej -
const db = require('./db')
const Query = {
studentById:(root,args,context,info) => {
return db.students.get(args.id);
}
}
const Mutation = {
createStudent:(root,args,context,info) => {
return db.students.create({collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName})
}
}
module.exports = {Query,Mutation}
Poniżej podano zapytanie o uzyskanie ucznia na podstawie unikalnego identyfikatora zwróconego z zapytania mutacji -
{
studentById(id:"SkQtxYBUm") {
id
firstName
lastName
}
}
Odpowiedź z serwera jest następująca -
{
"data": {
"studentById": {
"id": "SkQtxYBUm",
"firstName": "Tim",
"lastName":"George"
}
}
}
Zwracanie obiektu w mutacji
Najlepszą praktyką jest zwrócenie obiektu w mutacji. Na przykład aplikacja kliencka chce pobrać dane dotyczące studentów i uczelni. W takim przypadku, zamiast wysyłać dwa różne żądania, możemy utworzyć zapytanie zwracające obiekt zawierający dane studentów i ich uczelni.
Krok 1 - Edytuj plik schematu
Dodaj nową metodę o nazwie addStudent która zwraca obiekt w typie mutacji schema.graphql.
Dowiedzmy się, jak uzyskać dostęp do szczegółów uczelni poprzez dane studentów. Dodaj typ uczelni w pliku schematu.
type Mutation {
addStudent_returns_object(collegeId:ID,firstName:String,lastName:String):Student
createStudent(collegeId:ID,firstName:String,lastName:String):String
}
type College {
id:ID!
name:String
location:String
rating:Float
}
type Student {
id:ID!
firstName:String
lastName:String
college:College
}
Krok 2 - Zaktualizuj plik resolvers.js
Zaktualizuj plik resolvers.js w folderze projektu i dodaj następujący kod -
const Mutation = {
createStudent:(root,args,context,info) => {
return db.students.create({
collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName
})
},
// new resolver function
addStudent_returns_object:(root,args,context,info) => {
const id = db.students.create({
collegeId:args.collegeId,
firstName:args.firstName,
lastName:args.lastName
})
return db.students.get(id)
}
}
//for each single student object returned,resolver is invoked
const Student = {
college:(root) => {
return db.colleges.get(root.collegeId);
}
}
module.exports = {Query,Student,Mutation}
Krok 3 - Uruchom serwer i wpisz zapytanie w GraphiQL
Następnie uruchomimy serwer i zażądamy zapytania w GraphiQL z następującym kodem -
mutation {
addStudent_returns_object(collegeId:"col-101",firstName:"Susan",lastName:"George") {
id
firstName
college{
id
name
}
}
}
Powyższe zapytanie dodaje nowego ucznia i pobiera obiekt studenta wraz z obiektem uczelni. Oszczędza to wycieczki w obie strony do serwera.
Odpowiedź jest taka, jak podano poniżej -
{
"data": {
"addStudent_returns_object": {
"id": "rklUl08IX",
"firstName": "Susan",
"college": {
"id": "col-101",
"name": "AMU"
}
}
}
}
Podczas dodawania lub modyfikowania danych ważne jest, aby sprawdzić poprawność danych wejściowych użytkownika. Na przykład może być konieczne upewnienie się, że wartość pola zawsze nie jest zerowa. Możemy użyć! (non-nullable) znacznik typu w GraphQL, aby przeprowadzić taką walidację.
Składnia korzystania z ! znacznik typu jest taki, jak podano poniżej -
type TypeName {
field1:String!,
field2:String!,
field3:Int!
}
Powyższa składnia zapewnia, że wszystkie pola nie są puste.
Jeśli chcemy zaimplementować dodatkowe reguły, takie jak sprawdzanie długości łańcucha lub sprawdzanie, czy liczba mieści się w podanym zakresie, możemy zdefiniować niestandardowe walidatory. Niestandardowa logika walidacji będzie częścią funkcji przelicznika. Zrozummy to na przykładzie.
Ilustracja - Wdrażanie niestandardowych walidatorów
Stwórzmy formularz rejestracyjny z podstawową walidacją. Formularz będzie zawierał pola e-mail, imię i hasło.
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder o nazwie validation-app. Zmień katalog na validation-app z terminala. Wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
Dodaj schema.graphql plik w folderze projektu validation-app i dodaj następujący kod -
type Query {
greeting:String
}
type Mutation {
signUp(input:SignUpInput):String
}
input SignUpInput {
email:String!,
password:String!,
firstName:String!
}
Note- Możemy użyć typu wejścia SignUpInput, aby zmniejszyć liczbę parametrów w funkcji signUp. Tak więc funkcja signUp przyjmuje tylko jeden parametr typu SignUpInput.
Krok 3 - Utwórz resolwery
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const Query = {
greeting:() => "Hello"
}
const Mutation ={
signUp:(root,args,context,info) => {
const {email,firstName,password} = args.input;
const emailExpression = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
const isValidEmail = emailExpression.test(String(email).toLowerCase())
if(!isValidEmail)
throw new Error("email not in proper format")
if(firstName.length > 15)
throw new Error("firstName should be less than 15 characters")
if(password.length < 8 )
throw new Error("password should be minimum 8 characters")
return "success";
}
}
module.exports = {Query,Mutation}
Funkcja resolver, signUp akceptuje parametry e-mail, hasło i imię. Zostaną one przekazane przez zmienną wejściową, aby można było uzyskać do nich dostęp przez args.input.
Krok 4 - Uruchom aplikację
Utwórz plik server.js. Zobacz krok 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj użyjemy GraphiQL jako klienta do przetestowania aplikacji.
Otwórz przeglądarkę i wprowadź adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
mutation doSignUp($input:SignUpInput) { signUp(input:$input)
}
Ponieważ wejście do funkcji rejestracji jest typem złożonym, musimy użyć zmiennych zapytania w graphiql. W tym celu musimy najpierw nadać zapytaniu nazwę i nazwać je doSignUp, $ input jest zmienną zapytania.
Następującą zmienną zapytania należy wprowadzić w zakładce zmienne zapytania w graphiql -
{
"input":{
"email": "abc@abc",
"firstName": "kannan",
"password": "pass@1234"
}
}
Tablica błędów zawiera szczegóły błędów walidacji, jak pokazano poniżej -
{
"data": {
"signUp": null
},
"errors": [
{
"message": "email not in proper format",
"locations": [
{
"line": 2,
"column": 4
}
],
"path": [
"signUp"
]
}
]
}
Musimy wprowadzić odpowiednie dane wejściowe dla każdego pola, jak podano poniżej -
{
"input":{
"email": "[email protected]",
"firstName": "kannan",
"password": "pass@1234"
}
}
Odpowiedź jest następująca -
{
"data": {
"signUp": "success"
}
}
Tutaj w poniższym zapytaniu nie przypisujemy żadnego hasła.
{
"input":{
"email": "[email protected]",
"firstName": "kannan"
}
}
Jeśli wymagane pole nie zostanie podane, serwer qraphql wyświetli następujący błąd -
{
"errors": [
{
"message": "Variable \"$input\" got invalid value {\"email\":\"[email protected]\",\"firstName\":\"kannan\"}; Field value.password of required type String! was not provided.",
"locations": [
{
"line": 1,
"column": 19
}
]
}
]
}
Aplikacje internetowe wysyłają i pobierają dane asynchronicznie (w tle). AJAX umożliwia stronom internetowym ładowanie treści na ekran bez odświeżania strony. jQuery zapewnia kilka metod działania AJAX, ułatwiając w ten sposób korzystanie z AJAX. W tym rozdziale dowiemy się, jak możemy zintegrować GraphQL z jQuery.
Rozważ aplikację korzystającą z architektury klient-serwer. Możemy zbudować zewnętrzną stronę internetową, która żąda danych z serwera GraphQL. Strona internetowa będzie wykonywać wywołania AJAX przy użyciu jQuery do serwera GraphQL.
Aby zintegrować GraphQL z JQuery, sprawdźmy nagłówki żądań GraphiQL i zrozummy parametry żądania.
Zacząć hello-worldapp (odpowiednia ilustracja znajduje się w rozdziale 6). Wpisz zapytanie graphql {powitanie} w oknie GraphiQL. Kliknij prawym przyciskiem myszy i sprawdź lub naciśnij (ctrl + shift + I) na chrome, aby przejść do karty sieci, jak pokazano poniżej -
Od prostego hello-world przykład, możemy to zrozumieć http method używany jest POST. Teraz w przeglądarce przewiń w dół do sekcji nagłówka, aby wyświetlić ładunek żądania .
Po kliknięciu view code, zobaczysz następujące informacje w sekcji żądania danych w chrome.
{"query":"{\n greeting\n}","variables":null,"operationName":null}
Zwróć także uwagę na adres URL żądania, http://localhost:9000/graphql który powinien zostać wywołany z aplikacji klienta.
Ilustracja
Pozwól nam zrozumieć, jak zintegrować GraphQL z JQuery przy użyciu procesu krokowego.
Konfigurowanie serwera
Dowiemy się, jak skonfigurować serwer, wykonując następujące kroki -
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder o nazwie jquery-server-app. Zmień katalog na jquery-server-app z poziomu terminala. Wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
Dodaj plik schema.graphql do folderu projektu jquery-server-app i dodaj następujący kod -
type Query
{
greeting: String
sayHello(name:String!):String
}
W pliku zdefiniowano dwa zapytania greeting i sayHello. Zapytanie sayHello przyjmuje parametr ciągu i zwraca inny ciąg. Parametr funkcji sayHello () nie ma wartości null.
Krok 3 - Utwórz resolwery
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const Query =
{
greeting: () => 'Hello GraphQL From TutorialsPoint !!' ,
sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL server says Hello to you!!`
}
module.exports = {Query}
Tutaj, greeting i sayHelloto dwa resolwery. W przeliczniku sayHello wartość przekazana do parametru name jest dostępna za pośrednictwem argumentów. Aby uzyskać dostęp do funkcji przelicznika poza modułem, obiekt Query należy wyeksportować za pomocąmodule.exports.
Krok 4 - Uruchom aplikację
Utwórz plik server.js. Zobacz krok 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji.
Otwórz przeglądarkę i wpisz adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
{
greeting,
sayHello(name:"Mohtashim")
}
Odpowiedź z serwera jest taka, jak podano poniżej -
{
"data": {
"greeting": "Hello GraphQL From TutorialsPoint !!",
"sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
}
}
Konfiguracja klienta
Ponieważ już skonfigurowaliśmy serwer, teraz nauczymy się, jak skonfigurować klienta.
Krok 1 - Utwórz nowy folder jquery-client-app poza bieżącym folderem projektu
Najpierw utworzymy folder o nazwie jquery-client-app poza folderem projektu.
Krok 2 - Utwórz stronę HTML index.html dla integracji jQuery
Stworzymy aplikację kliencką w jquery i wywołamy obie metody. Poniżej znajduje się kod dla index.html plik. Plik index.html strona wysyła żądania do serwera, gdy przyciski - Greet i SayHellosą klikane. Wykonamy asynchroniczne żądanie za pomocą funkcji $ .ajax ().
<!DOCTYPE html>
<html>
<head>
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() { $("#btnSayhello").click(function() {
const name = $("#txtName").val(); console.log(name); $("#SayhelloDiv").html('loading....');
$.ajax({url: "http://localhost:9000/graphql", contentType: "application/json",type:'POST', data: JSON.stringify({ query:`{ sayHello(name:"${name}")}`
}),
success: function(result) {
console.log(JSON.stringify(result))
$("#SayhelloDiv").html("<h1>"+result.data.sayHello +"</h1>"); } }); }); $("#btnGreet").click(function() {
$("#greetingDiv").html('loading....'); //https://kannan-first-graphql-app.herokuapp.com/graphql $.ajax({url: "http://localhost:9000/graphql",
contentType: "application/json",
type:'POST',
data: JSON.stringify({
query:`{greeting}`
}),
success: function(result) {
$("#greetingDiv").html("<h1>"+result.data.greeting+"</h1>");
}
});
});
});
</script>
</head>
<body>
<h1>Jquery Client </h1>
<hr/>
<section>
<button id = "btnGreet">Greet</button>
<br/> <br/>
<div id = "greetingDiv"> </div>
</section>
<br/> <br/> <br/>
<hr/>
<section>
Enter a name:<input id = "txtName" type = "text" value = "kannan"/>
<button id = "btnSayhello">SayHello</button>
<div id = "SayhelloDiv"> </div>
</section>
</body>
</html>
Otwórz ten plik w przeglądarce i kliknij przycisk, aby zobaczyć odpowiedź. Wynik będzie taki, jak podano poniżej -
React to biblioteka JavaScript do tworzenia interfejsów użytkownika. Ten rozdział wyjaśnia, w jaki sposób można zintegrować GraphQL z aplikacją React.
Ilustracja
Najszybszym sposobem skonfigurowania projektu React jest użycie narzędzia Create React App . W kolejnych sekcjach dowiemy się, jak skonfigurować zarówno serwer, jak i klienta.
Konfigurowanie serwera
Aby skonfigurować serwer, wykonaj poniższe czynności -
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder react-server-app. Zmień katalog na react-server-app z terminala. Wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
Dodaj schema.graphql plik w folderze projektu react-server-app i dodaj następujący kod -
type Query
{
greeting: String
sayHello(name:String!):String
}
W pliku zdefiniowano dwa zapytania - powitanie i przywitanie. Zapytanie sayHello przyjmuje parametr ciągu i zwraca inny ciąg. Parametr funkcji sayHello () nie ma wartości null.
Krok 3 - Utwórz resolwery
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const Query =
{
greeting: () => 'Hello GraphQL From TutorialsPoint !!' ,
sayHello:(root,args,context,info) => `Hi ${args.name} GraphQL server says Hello to you!!`
}
module.exports = {Query}
Tutaj powitanie i przywitanie to dwa resolwery. W przeliczniku sayHello wartość przekazana do parametru name jest dostępna za pośrednictwem args. Aby uzyskać dostęp do funkcji przelicznika poza modułem, obiekt Query musi zostać wyeksportowany za pomocą module.exports.
Krok 4 - Uruchom aplikację
Utwórz plik server.js. Zobacz krok 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji.
Otwórz przeglądarkę i wpisz adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
{
greeting,
sayHello(name:"Mohtashim")
}
Odpowiedź z serwera jest podana poniżej -
{
"data": {
"greeting": "Hello GraphQL From TutorialsPoint !!",
"sayHello": "Hi Mohtashim GraphQL server says Hello to you!!"
}
}
Konfiguracja klienta
Otwórz nowy terminal dla klienta. Terminal serwera powinien być uruchomiony przed uruchomieniem aplikacji klienckiej. Aplikacja React będzie działać na porcie numer 3000, a aplikacja serwerowa na porcie numer 9000.
Krok 1 - Utwórz klienta hello-world-client projektu React
W terminalu klienta wpisz następujące polecenie -
npx create-react-app hello-world-client
Spowoduje to zainstalowanie wszystkiego, co jest potrzebne w typowej aplikacji Reag. Pliknpx użyteczność i create-react-appnarzędzie stwórz projekt o nazwie hello-world-client. Po zakończeniu instalacji otwórz projekt w VSCode.
Krok 2 - Uruchom hello-world-client
Zmień bieżącą ścieżkę folderu w terminalu na hello-world-client. Wpisz npm start, aby uruchomić projekt. Spowoduje to uruchomienie serwera programistycznego na porcie 3000 i automatycznie otworzy przeglądarkę i załaduje stronę indeksu.
Jest to pokazane na zrzucie ekranu podanym poniżej -
Krok 3 - Zmodyfikuj składnik aplikacji
W folderze App.js w folderze src dodaj dwie funkcje, jedną do ładowania powitania, a drugą do ładowania wiadomości sayHello.
Poniżej znajduje się funkcja loadGreeting, która wysyła zapytanie GraphQL na powitanie.
async function loadGreeting() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:'{greeting}'})
})
const rsponseBody = await response.json();
return rsponseBody.data.greeting;
console.log("end of function")
}
Poniżej znajduje się loadSayhello funkcja, która wysyła zapytanie GraphQL dla sayHello -
async function loadSayhello(name) {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{sayHello(name:"${name}")}`})
})
}
Kompletny App.js plik jest pokazany poniżej -
import React, { Component } from 'react';
import logo from './logo.svg';
import './App.css';
async function loadGreeting() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:'{greeting}'})
})
const rsponseBody = await response.json();
return rsponseBody.data.greeting;
console.log("end of function")
}
async function loadSayhello(name) {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{sayHello(name:"${name}")}`})
})
const rsponseBody = await response.json();
return rsponseBody.data.sayHello;
}
class App extends Component {
constructor(props) {
super(props);
this.state = {greetingMessage:'',sayHelloMessage:'',userName:''}
this.updateName = this.updateName.bind(this);
this.showSayHelloMessage = this.showSayHelloMessage.bind(this);
this.showGreeting = this.showGreeting.bind(this);
}
showGreeting() {
loadGreeting().then(g => this.setState({greetingMessage:g+" :-)"}))
}
showSayHelloMessage() {
const name = this.state.userName;
console.log(name)
loadSayhello(name).then(m => this.setState({sayHelloMessage:m}))
}
updateName(event) {
this.setState({userName:event.target.value})
}
render() {
return (
<div className = "App">
<header className = "App-header">
<img src = {logo} className = "App-logo" alt = "logo" />
<h1 className = "App-title">Welcome to React</h1>
</header>
<br/><br/>
<section>
<button id = "btnGreet" onClick = {this.showGreeting}>Greet</button>
<br/> <br/>
<div id = "greetingDiv">
<h1>{this.state.greetingMessage}</h1>
</div>
</section>
<hr/>
<section>
Enter a name:<input id = "txtName" type = "text" onChange = {this.updateName}
value = {this.state.userName}/>
<button id = "btnSayhello" onClick = {this.showSayHelloMessage}>SayHello</button>
<br/>
user name is:{this.state.userName} <br/>
<div id = "SayhelloDiv">
<h1>{this.state.sayHelloMessage}</h1>
</div>
</section>
</div>
);
}
}
export default App;
Po uruchomieniu obu aplikacji kliknij przycisk powitania. Następnie wprowadź nazwę w polu tekstowym i kliknij przycisk sayHello. Wynik będzie taki, jak podano poniżej -
Użyliśmy serwera Apollo do zbudowania specyfikacji graphql po stronie serwera. Jest to szybki i łatwy do zbudowania serwer GraphQL gotowy do produkcji. Teraz zrozumiemy stronę klienta.
Klient Apollo to najlepszy sposób na wykorzystanie GraphQL do tworzenia aplikacji klienckich. Klient został zaprojektowany, aby pomóc programistom szybko zbudować interfejs użytkownika, który pobiera dane za pomocą GraphQL i może być używany z dowolnym interfejsem JavaScript.
Klient Apollo obsługuje następujące platformy -
Sr.No. | Platforma i ramy |
---|---|
1 | Javascript React, Angular, Vue, Meteor, Ember |
2 | WebComponents Polimer, lit-apollo |
3 | Native Mobile Natywny Android z Javą, Natywny iOS z Swift |
Buforowanie jest jedną z głównych funkcji klienta Apollo. apollo-boost jest wygodnym pakietem, który wprowadza szereg innych zależności.
Ilustracja
Zobaczmy, jak używać klienta Apollo do tworzenia aplikacji klienckich, wykonując następujące czynności -
Konfigurowanie serwera
Musimy wykonać poniższe kroki, aby skonfigurować serwer -
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder apollo-server-app. Zmień katalog na apollo-server-app z terminala. Następnie wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
Dodaj schema.graphql plik w folderze projektu apollo-server-app i dodaj następujący kod -
type Query
{
students:[Student]
}
type Student {
id:ID!
firstName:String
lastName:String
college:College
}
type College {
id:ID!
name:String
location:String
rating:Float
}
Krok 3 - Dodaj resolwery
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const db = require('./db')
const Query = {
//resolver function for students returns list
students:() => db.students.list(),
}
const Student = {
college:(root) => {
return db.colleges.get(root.collegeId);
}
}
module.exports = {Query,Student}
Krok 4 - Uruchom aplikację
Stwórz server.jsplik. Zobacz krok 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj użyjemy GraphiQL jako klienta do przetestowania aplikacji.
Otwórz przeglądarkę i wpisz adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze.
{
students{
id
firstName
college{
name
}
}
}
Odpowiedź na zapytanie jest podana poniżej -
{
"data": {
"students": [
{
"id": "S1001",
"firstName": "Mohtashim",
"college": {
"name": "CUSAT"
}
},
{
"id": "S1002",
"firstName": "Kannan",
"college": {
"name": "AMU"
}
},
{
"id": "S1003",
"firstName": "Kiran",
"college": {
"name": "AMU"
}
}
]
}
}
Konfiguracja klienta
Otwórz nowy terminal dla klienta. Terminal serwera powinien być uruchomiony przed uruchomieniem aplikacji klienckiej. Aplikacja React będzie działać na porcie numer 3000, a aplikacja serwerowa na porcie numer 9000.
Krok 1 - Utwórz aplikację React
W terminalu klienta wpisz następujące polecenie -
npx create-react-app hello-world-client
Spowoduje to zainstalowanie wszystkiego, co jest potrzebne w typowej aplikacji Reag. Narzędzie npx i narzędzie create-react-app tworzą projekt z nazwąhello-world-client. Po zakończeniu instalacji otwórz projekt w VSCode.
Krok 2 - Uruchom hello-world-client
Zmień bieżącą ścieżkę folderu w terminalu na hello-world-client. Wpisz npm start, aby uruchomić projekt. Spowoduje to uruchomienie serwera programistycznego na porcie 3000 i automatycznie otworzy przeglądarkę i załaduje stronę indeksu.
Jest to pokazane na zrzucie ekranu podanym poniżej -
Krok 3 - Zainstaluj biblioteki klienckie Apollo
Aby zainstalować klienta Apollo, otwórz nowy terminal i znajdź bieżącą ścieżkę do folderu projektu. Wpisz następujące polecenie -
npm install apollo-boost graphql
Spowoduje to pobranie bibliotek graphql po stronie klienta, a także pakietu Apollo Boost. Możemy to sprawdzić, wpisując widok npm w zależnościach apollo-boost. Będzie to miało wiele zależności, jak pokazano poniżej -
{
'apollo-cache': '^1.1.15',
'apollo-cache-inmemory': '^1.2.8',
'apollo-client': '^2.4.0',
'apollo-link': '^1.0.6',
'apollo-link-error': '^1.0.3',
'apollo-link-http': '^1.3.1',
'apollo-link-state': '^0.4.0',
'graphql-tag': '^2.4.2'
}
Widzimy wyraźnie, że biblioteka Apollo-Client jest zainstalowana.
Krok 4 - Zmodyfikuj składnik aplikacji w pliku index.js
Dzięki Apollo Client możemy bezpośrednio wywołać serwer bez użycia Fetch API. Ponadto zapytania i mutacje nie powinny być osadzane w łańcuchu utworzonym w notacji zwrotnej. To dlatego, żegqlfunction bezpośrednio analizuje zapytania. Oznacza to, że programista może bezpośrednio pisać zapytania w ten sam sposób podczas pisania zapytań w narzędziu GraphiQL. gql jest funkcją znacznika, która parsuje ciąg szablonu zapisany w notacji zwrotnej do obiektu zapytania graphql. Metoda zapytania Apollo Client zwraca obietnicę.
Poniższy fragment kodu pokazuje, jak zaimportować klienta Apollo -
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const endPointUrl = 'http://localhost:9000/graphql'
const client = new ApolloClient({
link: new HttpLink({uri:endPointUrl}),
cache:new InMemoryCache()
});
W poprzednim rozdziale omówiliśmy, jak używać funkcji fetch API dla żądań HTTP. Poniższy kod pokazuje, jak używaćgqlfunkcjonować. PlikloadStudentsAsync funkcja używa klienta graphql do wysyłania zapytań do serwera.
async function loadStudentsAsync() {
const query = gql`
{
students{
id
firstName
lastName
college{
name
}
}
}`
const {data} = await client.query({query}) ;
return data.students;
}
Musisz tylko zachować index.js w srcfolder i index.html w folderze publicznym; wszystkie inne pliki, które są generowane automatycznie, można usunąć.
Strukturę katalogów podano poniżej -
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
-->package.json
Poniżej znajduje się index.js w aplikacji reagującej -
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
// apollo client
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
import gql from 'graphql-tag'
const endPointUrl = 'http://localhost:9000/graphql'
const client = new ApolloClient({
link: new HttpLink({uri:endPointUrl}),
cache:new InMemoryCache()
});
async function loadStudentsAsync() {
const query = gql`
{
students{
id
firstName
lastName
college{
name
}
}
}
`
const {data} = await client.query({query}) ;
return data.students;
}
class App extends Component {
constructor(props) {
super(props);
this.state = {
students:[]
}
this.studentTemplate = [];
}
async loadStudents() {
const studentData = await loadStudentsAsync();
this.setState({
students: studentData
})
console.log("loadStudents")
}
render() {
return(
<div>
<input type = "button" value = "loadStudents" onClick = {this.loadStudents.bind(this)}/>
<div>
<br/>
<hr/>
<table border = "3">
<thead>
<tr>
<td>First Name</td>
<td>Last Name</td>
<td>college Name</td>
</tr>
</thead>
<tbody>
{
this.state.students.map(s => {
return (
<tr key = {s.id}>
<td>
{s.firstName}
</td>
<td>
{s.lastName}
</td>
<td>
{s.college.name}
</td>
</tr>
)
})
}
</tbody>
</table>
</div>
</div>
)
}
}
ReactDOM.render(<App/>, document.getElementById('root'));
Aplikacja React załaduje studentów z serwera GraphQL, po kliknięciu przycisku loadStudents, jak pokazano poniżej -
Uwierzytelnianie to proces lub czynność polegająca na weryfikacji tożsamości użytkownika lub procesu. Ważne jest, aby aplikacja uwierzytelniała użytkownika, aby zapewnić, że dane nie są dostępne dla anonimowego użytkownika. W tej sekcji dowiemy się, jak uwierzytelnić klienta GraphQL.
Express JWT
W tym przykładzie użyjemy jQuery do stworzenia aplikacji klienckiej. Do uwierzytelniania żądań będziemy używać express-jwt moduł po stronie serwera.
Moduł express-jwt to oprogramowanie pośredniczące, które umożliwia uwierzytelnianie żądań HTTP przy użyciu tokenów JWT. JSON Web Token (JWT) to długi ciąg identyfikujący zalogowanego użytkownika.
Po pomyślnym zalogowaniu się użytkownika serwer generuje token JWT. Ten token wyraźnie identyfikuje dziennik. Innymi słowy, token reprezentuje tożsamość użytkownika. Więc następnym razem, gdy klient przyjdzie na serwer, musi przedstawić ten token, aby uzyskać wymagane zasoby. Klientem może być aplikacja mobilna lub aplikacja internetowa.
Ilustracja
Aby zrozumieć tę ilustrację, będziemy postępować według stopniowej procedury.
Konfigurowanie serwera
Poniżej przedstawiono kroki konfiguracji serwera -
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder auth-server-app. Zmień katalog na auth-server-app z terminala. Wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
schema.graphql auth-server-apptype Query
{
greetingWithAuth:String
}
Krok 3 - Dodaj resolwery
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
Resolver sprawdzi, czy uwierzytelniony obiekt użytkownika jest dostępny w obiekcie kontekstu GraphQL. Zgłosi wyjątek, jeśli uwierzytelniony użytkownik nie jest dostępny.
const db = require('./db')
const Query = {
greetingWithAuth:(root,args,context,info) => {
//check if the context.user is null
if (!context.user) {
throw new Error('Unauthorized');
}
return "Hello from TutorialsPoint, welcome back : "+context.user.firstName;
}
}
module.exports = {Query}
Krok 4 - Utwórz plik Server.js.
Oprogramowanie pośredniczące uwierzytelniania uwierzytelnia wywołujące przy użyciu tokenu internetowego JSON. Adres URL do uwierzytelniania to http://localhost:9000/login.
To jest operacja pocztowa. Użytkownik musi podać swój adres e-mail i hasło, które zostaną zweryfikowane z zaplecza. Jeśli prawidłowy token zostanie wygenerowany metodą jwt.sign, klient będzie musiał przesyłać go w nagłówku dla kolejnych żądań.
Jeśli token jest ważny, req.user zostanie ustawiony z zdekodowanym obiektem JSON do wykorzystania przez późniejsze oprogramowanie pośredniczące do autoryzacji i kontroli dostępu.
Poniższy kod używa dwóch modułów - jsonwebtoken i express-jwt do uwierzytelniania żądań -
Gdy użytkownik kliknie plik greetprzycisku, wysyłane jest żądanie trasy / graphql. Jeśli użytkownik nie jest uwierzytelniony, zostanie poproszony o uwierzytelnienie się.
Użytkownik otrzymuje formularz, który akceptuje identyfikator e-mail i hasło. W naszym przykładzie trasa / login jest odpowiedzialna za uwierzytelnianie użytkownika.
Trasa / login sprawdza, czy w bazie danych znaleziono dopasowanie dla poświadczeń podanych przez użytkownika.
Jeśli poświadczenia są nieprawidłowe, do użytkownika zwracany jest wyjątek HTTP 401.
Jeśli poświadczenia są prawidłowe, serwer generuje token. Ten token jest wysyłany jako część odpowiedzi do użytkownika. Odbywa się to za pomocą funkcji jwt.sign.
const expressJwt = require('express-jwt');
const jwt = require('jsonwebtoken');
//private key
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
app.post('/login', (req, res) => {
const {email, password} = req.body;
//check database
const user = db.students.list().find((user) => user.email === email);
if (!(user && user.password === password)) {
res.sendStatus(401);
return;
}
//generate a token based on private key, token doesn't have an expiry
const token = jwt.sign({sub: user.id}, jwtSecret);
res.send({token});
});
Dla każdego żądania zostanie wywołana funkcja app.use (). To z kolei spowoduje wywołanie oprogramowania pośredniczącego expressJWT. To oprogramowanie pośredniczące dekoduje token sieciowy JSON. Identyfikator użytkownika przechowywany w tokenie zostanie pobrany i zapisany jako użytkownik właściwości w obiekcie żądania.
//decodes the JWT and stores in request object
app.use(expressJwt({
secret: jwtSecret,
credentialsRequired: false
}));
Aby udostępnić właściwość użytkownika w kontekście GraphQL, ta właściwość jest przypisana do context obiekt, jak pokazano poniżej -
//Make req.user available to GraphQL context
app.use('/graphql', graphqlExpress((req) => ({
schema,
context: {user: req.user &&apm; db.students.get(req.user.sub)}
})));
Stwórz server.js w bieżącej ścieżce folderu. Kompletny plik server.js wygląda następująco -
const bodyParser = require('body-parser');
const cors = require('cors');
const express = require('express');
const expressJwt = require('express-jwt'); //auth
const jwt = require('jsonwebtoken'); //auth
const db = require('./db');
var port = process.env.PORT || 9000
const jwtSecret = Buffer.from('Zn8Q5tyZ/G1MHltc4F/gTkVJMlrbKiZt', 'base64');
const app = express();
const fs = require('fs')
const typeDefs = fs.readFileSync('./schema.graphql',{encoding:'utf-8'})
const resolvers = require('./resolvers')
const {makeExecutableSchema} = require('graphql-tools')
const schema = makeExecutableSchema({typeDefs, resolvers})
app.use(cors(), bodyParser.json(), expressJwt({
secret: jwtSecret,
credentialsRequired: false
}));
const {graphiqlExpress,graphqlExpress} = require('apollo-server-express')
app.use('/graphql', graphqlExpress((req) => ({
schema,
context: {user: req.user && db.students.get(req.user.sub)}
})));
app.use('/graphiql',graphiqlExpress({endpointURL:'/graphql'}))
//authenticate students
app.post('/login', (req, res) => {
const email = req.body.email;
const password = req.body.password;
const user = db.students.list().find((user) => user.email === email);
if (!(user && user.password === password)) {
res.sendStatus(401);
return;
}
const token = jwt.sign({sub: user.id}, jwtSecret);
res.send({token});
});
app.listen(port, () => console.info(`Server started on port ${port}`));
Krok 5 - Uruchom aplikację
Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj używamy GraphiQL jako klienta do testowania aplikacji.
Otwórz przeglądarkę i wpisz adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
{
greetingWithAuth
}
W poniższej odpowiedzi otrzymaliśmy błąd, ponieważ nie jesteśmy uwierzytelnionym użytkownikiem.
{
"data": {
"greetingWithAuth": null
},
"errors": [
{
"message": "Unauthorized",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"greetingWithAuth"
]
}
]
}
W następnej sekcji stwórzmy aplikację kliencką do uwierzytelniania.
Konfigurowanie klienta JQuery
W aplikacji klienckiej dostępny jest przycisk powitania, który wywoła schemat greetingWithAuth. Jeśli klikniesz przycisk bez logowania, wyświetli się komunikat o błędzie, jak poniżej -
Po zalogowaniu się użytkownikiem dostępnym w bazie danych pojawi się następujący ekran -
Mieć dostęp greeting, musimy najpierw uzyskać dostęp do adresu URL http://localhost:9000/login trasa jak poniżej.
Odpowiedź będzie zawierała token wygenerowany z serwera.
$.ajax({
url:"http://localhost:9000/login",
contentType:"application/json",
type:"POST",
data:JSON.stringify({email,password}),
success:function(response) {
loginToken = response.token;
$('#authStatus') .html("authenticated successfully") .css({"color":"green",'font-weight':'bold'}); $("#greetingDiv").html('').css({'color':''});
},
error:(xhr,err) => alert('error')
})
Po pomyślnym zalogowaniu możemy uzyskać dostęp do schematu greetingWithAuth, jak podano poniżej. Powinien istnieć nagłówek Authorizationheader dla wszystkich kolejnych żądań z tokenem okaziciela.
{
url: "http://localhost:9000/graphql",
contentType: "application/json",
headers: {"Authorization": 'bearer '+loginToken}, type:'POST',
data: JSON.stringify({
query:`{greetingWithAuth}`
}
Poniżej znajduje się kod dla index.html -
<!DOCTYPE html>
<html>
<head>
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script>
$(document).ready(function() { let loginToken = ""; $("#btnGreet").click(function() {
$.ajax({url: "http://localhost:9000/graphql", contentType: "application/json", headers: {"Authorization": 'bearer '+loginToken}, type:'POST', data: JSON.stringify({ query:`{greetingWithAuth}` }), success: function(result) { $("#greetingDiv").html("<h1>"+result.data.greetingWithAuth+"</h1>")
},
error:function(jQxhr,error) {
if(jQxhr.status == 401) {
$("#greetingDiv").html('please authenticate first!!') .css({"color":"red",'font-weight':'bold'}) return; } $("#greetingDiv").html('error').css("color","red");
}
});
});
$('#btnAuthenticate').click(function() { var email = $("#txtEmail").val();
var password = $("#txtPwd").val(); if(email && password) { $.ajax({
url:"http://localhost:9000/login",
contentType:"application/json",
type:"POST",
data:JSON.stringify({email,password}),
success:function(response) {
loginToken = response.token;
$('#authStatus') .html("authenticated successfully") .css({"color":"green",'font-weight':'bold'}); $("#greetingDiv").html('').css({'color':''});
},
error:(xhr,err) => alert('error')
})
}else alert("email and pwd empty")
})
});
</script>
</head>
<body>
<h1> GraphQL Authentication </h1>
<hr/>
<section>
<button id = "btnGreet">Greet</button>
<br/> <br/>
<div id = "greetingDiv"></div>
</section>
<br/> <br/> <br/>
<hr/>
<section id = "LoginSection">
<header>
<h2>*Login first to access greeting </h2>
</header>
<input type = "text" value = "[email protected]" placeholder = "enter email" id = "txtEmail"/>
<br/>
<input type = "password" value = "pass123" placeholder = "enter password" id = "txtPwd"/>
<br/>
<input type = "button" id = "btnAuthenticate" value = "Login"/>
<p id = "authStatus"></p>
</section>
</body>
</html>
Buforowanie to proces przechowywania danych w tymczasowym obszarze pamięci o nazwie cache. Po powrocie do ostatnio odwiedzonej strony przeglądarka może pobrać te pliki z pamięci podręcznej, a nie z oryginalnego serwera. Oszczędza to czas i sieć przed obciążeniem dodatkowym ruchem.
Aplikacje klienckie współpracujące z GraphQL są odpowiedzialne za buforowanie danych na ich końcu. Jednym z możliwych wzorców jest zarezerwowanie pola, takiego jak id, jako globalnego unikalnego identyfikatora.
InMemory Cache
InMemoryCache to znormalizowany magazyn danych powszechnie używany w aplikacjach klienckich GraphQL bez użycia innej biblioteki, takiej jak Redux.
Przykładowy kod do użycia InMemoryCache z ApolloClient jest podany poniżej -
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
const cache = new InMemoryCache();
const client = new ApolloClient({
link: new HttpLink(),
cache
});
Konstruktor InMemoryCache przyjmuje opcjonalny obiekt konfiguracyjny z właściwościami umożliwiającymi dostosowanie pamięci podręcznej.
Sr.No. | Parametr i opis |
---|---|
1 | addTypename Wartość logiczna określająca, czy dodać __typename do dokumentu (domyślnie: true) |
2 | dataIdFromObject Funkcja, która przyjmuje obiekt danych i zwraca unikalny identyfikator, który ma być używany podczas normalizowania danych w sklepie |
3 | fragmentMatcher Domyślnie InMemoryCache używa heurystycznego dopasowania fragmentów |
4 | cacheRedirects Mapa funkcji do przekierowania zapytania do innego wpisu w pamięci podręcznej przed wysłaniem żądania. |
Ilustracja
Stworzymy aplikację jednostronicową w ReactJS z dwoma zakładkami - jedną dla zakładki domowej i drugą dla studentów. Karta studentów załaduje dane z API serwera GraphQL. Aplikacja zapyta o dane uczniów, gdy użytkownik przejdzie z karty głównej do karty uczniów. Wynikowe dane zostaną zapisane w pamięci podręcznej aplikacji.
Zapytamy również o czas serwera za pomocą getTimepole do sprawdzenia, czy strona jest buforowana. Jeśli dane zostaną zwrócone z pamięci podręcznej, strona wyświetli czas pierwszego żądania wysłanego do serwera. Jeśli dane są wynikiem nowego żądania skierowanego do serwera, zawsze będzie pokazywał najnowszy czas z serwera.
Konfigurowanie serwera
Poniżej przedstawiono kroki konfiguracji serwera -
Krok 1 - Pobierz i zainstaluj wymagane zależności dla projektu
Utwórz folder cache-server-app. Zmień katalog na cache-server-app z terminala. Wykonaj kroki od 3 do 5 opisane w rozdziale Konfiguracja środowiska.
Krok 2 - Utwórz schemat
Dodaj schema.graphql plik w folderze projektu cache-server-app i dodaj następujący kod -
type Query {
students:[Student]
getTime:String
}
type Student {
id:ID!
firstName:String
lastName:String
fullName:String
}
Krok 3 - Dodaj resolwery
Utwórz plik resolvers.js w folderze projektu i dodaj następujący kod -
const db = require('./db')
const Query = {
students:() => db.students.list(),
getTime:() => {
const today = new Date();
var h = today.getHours();
var m = today.getMinutes();
var s = today.getSeconds();
return `${h}:${m}:${s}`;
}
}
module.exports = {Query}
Krok 4 - Uruchom aplikację
Utwórz plik server.js. Zobacz krok 8 w rozdziale Konfiguracja środowiska. Wykonaj polecenie npm start w terminalu. Serwer będzie działał na porcie 9000. Tutaj użyjemy GraphiQL jako klienta do przetestowania aplikacji.
Otwórz przeglądarkę i wprowadź adres URL http://localhost:9000/graphiql. Wpisz następujące zapytanie w edytorze -
{
getTime
students {
id
firstName
}
}
Przykładowa odpowiedź zawiera nazwiska uczniów i czas serwera.
{
"data": {
"getTime": "22:18:42",
"students": [
{
"id": "S1001",
"firstName": "Mohtashim"
},
{
"id": "S1002",
"firstName": "Kannan"
},
{
"id": "S1003",
"firstName": "Kiran"
}
]
}
}
Konfigurowanie klienta ReactJS
Otwórz nowy terminal dla klienta. Terminal serwera powinien być uruchomiony przed uruchomieniem aplikacji klienckiej. Aplikacja React będzie działać na porcie numer 3000, a aplikacja serwerowa na porcie numer 9000.
Krok 1 - Utwórz aplikację React
W terminalu klienta wpisz następujące polecenie -
npx create-react-app hello-world-client
Spowoduje to zainstalowanie wszystkiego, co jest potrzebne w typowej aplikacji Reag. Pliknpx utility i create-react-appnarzędzia tworzą projekt o nazwie hello-world-client. Po zakończeniu instalacji otwórz projekt w VSCode.
Zainstaluj moduły routera do reakcji za pomocą następującego polecenia - npm install react-router-dom.
Krok 2 - Uruchom hello-world-client
Zmień bieżącą ścieżkę folderu w terminalu na hello-world-client. Wpisz npm start, aby uruchomić projekt. Spowoduje to uruchomienie serwera programistycznego na porcie 3000 i automatycznie otworzy przeglądarkę i załaduje stronę indeksu.
Jest to pokazane na zrzucie ekranu podanym poniżej -
Krok 3 - Zainstaluj biblioteki klienckie Apollo
Aby zainstalować klienta Apollo, otwórz nowy terminal i znajdź bieżącą ścieżkę do folderu projektu. Wpisz następujące polecenie -
npm install apollo-boost graphql
Spowoduje to pobranie bibliotek graphql po stronie klienta, a także pakietu Apollo Boost. Możemy to zweryfikować, wpisując zależności apollo-boost npm view. Będzie to miało wiele zależności, jak pokazano poniżej -
{
'apollo-cache': '^1.1.15',
'apollo-cache-inmemory': '^1.2.8',
'apollo-client': '^2.4.0',
'apollo-link': '^1.0.6',
'apollo-link-error': '^1.0.3',
'apollo-link-http': '^1.3.1',
'apollo-link-state': '^0.4.0',
'graphql-tag': '^2.4.2'
}
Widzimy wyraźnie, że biblioteka klienta apollo jest zainstalowana.
Krok 4 - Zmodyfikuj składnik aplikacji w pliku index.js
Aby uzyskać prostą aplikację reagowania, wystarczy zachować rozszerzenie index.js w src folder i index.htmlw folderze publicznym; wszystkie inne pliki, które są generowane automatycznie, można usunąć.
Strukturę katalogów podano poniżej -
hello-world-client /
-->node_modules
-->public
index.html
-->src
index.js
students.js
-->package.json
Dodaj dodatkowy plik Students.js, który będzie zawierał składnik Students. Szczegóły ucznia są pobierane za pośrednictwem komponentu ucznia. W składniku aplikacji używamy HashRoutera.
Poniżej znajduje się index.js w aplikacji reagującej -
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {HashRouter, Route, Link} from 'react-router-dom'
//components
import Students from './students'
class App extends Component {
render() {
return(
<div><h1>Home !!</h1>
<h2>Welcome to React Application !! </h2>
</div>
)
}
}
function getTime() {
var d = new Date();
return d.getHours()+":"+d.getMinutes()+":"+d.getSeconds()
}
const routes = <HashRouter>
<div>
<h4>Time from react app:{getTime()}</h4>
<header>
<h1> <Link to="/">Home</Link>
<Link to = "/students">Students</Link> </h1>
</header>
<Route exact path = "/students" component = {Students}></Route>
<Route exact path = "/" component = {App}></Route>
</div>
</HashRouter>
ReactDOM.render(routes, document.querySelector("#root"))
Krok 5 - Edytuj uczniów składowych w Students.js
W komponencie dla studentów zastosujemy następujące dwa podejścia do ładowania danych -
Fetch API (loadStudents_noCache) - Spowoduje to wyświetlenie nowego żądania za każdym razem, gdy kliknie kartę ucznia.
Apollo Client (loadWithApolloclient) - Spowoduje to pobranie danych z pamięci podręcznej.
Dodaj funkcję loadWithApolloclientktóry pyta o studentów i czas z serwera. Ta funkcja umożliwi buforowanie. Tutaj używamy funkcji gql do analizowania zapytania.
async loadWithApolloclient() {
const query = gql`{
getTime
students {
id
firstName
}
}`;
const {data} = await client.query({query})
return data;
}
Plik Fetch APIto prosty interfejs do pobierania zasobów. Funkcja Fetch ułatwia tworzenie żądań internetowych i obsługę odpowiedzi niż w przypadku starszego XMLHttpRequest. Poniższa metoda pokazuje ładowanie danych bezpośrednio za pomocą api pobierania -
async loadStudents_noCache() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{
getTime
students {
id
firstName
}
}`})
})
const rsponseBody = await response.json();
return rsponseBody.data;
}
W konstruktorze StudentsComponent wywołaj loadWithApolloClientmetoda. Kompletny Student.js plik jest poniżej -
import React, {Component} from 'react';
import { Link} from 'react-router-dom'
//Apollo Client
import {ApolloClient, HttpLink, InMemoryCache} from 'apollo-boost'
import gql from 'graphql-tag'
const client = new ApolloClient({
link: new HttpLink({uri:`http://localhost:9000/graphql`}),
cache:new InMemoryCache()
})
class Students extends Component {
constructor(props) {
super(props);
this.state = {
students:[{id:1,firstName:'test'}],
serverTime:''
}
this.loadWithApolloclient().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
}
async loadStudents_noCache() {
const response = await fetch('http://localhost:9000/graphql', {
method:'POST',
headers:{'content-type':'application/json'},
body:JSON.stringify({query:`{
getTime
students {
id
firstName
}
}`})
})
const rsponseBody = await response.json();
return rsponseBody.data;
}
async loadWithApolloclient() {
console.log("inside apollo client function")
const query = gql`{
getTime
students {
id
firstName
}
}`;
const {data} = await client.query({query})
return data;
}
render() {
return(
<div>
<h3>Time from GraphQL server :{this.state.serverTime}</h3>
<p>Following Students Found </p>
<div>
<ul>
{
this.state.students.map(s => {
return(
<li key = {s.id}>
{s.firstName}
</li>
)
})
}
</ul>
</div>
</div>
)
}
}
export default Students
Krok 6 - Uruchom aplikację React z npm start
Możesz przetestować aplikację reagując, przechodząc z zakładki głównej do zakładki studenci. Po załadowaniu zakładki uczniów danymi z serwera. Będzie buforować dane. Możesz to przetestować, przechodząc kilka razy z domu do karty uczniów. Wynik będzie taki, jak pokazano poniżej -
Jeśli najpierw załadowałeś stronę uczniów, wpisując adres URL, http://localhost:3000/#/students, widać, że czas ładowania aplikacji React i GraphQL byłby w przybliżeniu taki sam. Po tym, jeśli przełączysz się do widoku głównego i powrócisz do serwera GraphQL, czas się nie zmieni. To pokazuje, że dane są buforowane.
Krok 7 - Zmień wywołanie loadWithApolloclient na loadStudents_noCache
Jeśli zmienisz metodę ładowania na loadStudents_noCachew konstruktorze StudentComponent dane wyjściowe nie będą buforować danych. To pokazuje różnicę między buforowaniem a brakiem buforowania.
this.loadStudents_noCache().then(data => {
this.setState({
students:data.students,
serverTime:data.getTime
})
})
Z powyższego wyniku jasno wynika, że jeśli przełączasz się między kartami, czas z serwera graphql będzie zawsze najnowszy, co oznacza, że dane nie są buforowane.