Въведение в GraphQL: как работи и как да го използваме

Снимка на Мат Дънкан на Unsplash

GraphQL е език за заявки за API на API. Той показва какви са различните видове данни, предоставени от сървъра и след това клиентът може да избере точно това, което иска.

Също така в GraphQL можете да получите множество сървърни ресурси в едно обаждане, а не да извършвате няколко REST API повиквания.

Можете да разгледате https://graphql.org/ за пълния списък на предимствата.

Работата е там, докато не видите GraphQL в действие, трудно е да разберете ползите. Така че нека започнем с използването на GraphQL.

В тази статия ще използваме GraphQL заедно с NodeJS.

Предварителни условия

Инсталирайте NodeJS от тук: https://nodejs.org/en/.

Как да използвате GraphQL с NodeJs

GraphQL може да се използва с няколко езика. Тук ще се съсредоточим върху това как можем да използваме GraphQL с JavaScript, използвайки NodeJS.

Създайте папка, наречена graphql-with-nodejs. Отидете в папката на проекта и стартирайте npm init, за да създадете проекта NodeJS. Командата за това е дадена по-долу.

cd graphql-with-nodejs
npm init

Инсталирайте зависимостите

Инсталирайте Express с помощта на следната команда:

npm инсталирайте express

Инсталирайте GraphQL, като използвате следната команда. Ще инсталираме GraphQL и GraphQL за Express.

npm инсталирайте express-graphql graphql

Код на NodeJS

Създайте файл наречен server.js вътре в проекта и копирайте следния код в него:

const express = изисквам ('express');
const порт = 5000;
const app = express ();

app.get ('/ здравей', (req, res) => {
    res.send ( "здравей");
   }
);

app.listen (порт);
console.log (`Сървър работи в localhost: $ {port}`);

Горният код има една единствена HTTP GET крайна точка, наречена / здравей.

Крайната точка се създава с помощта на Express.

Сега нека модифицираме този код, за да активираме GraphQL.

Активиране на GraphQL в кода

GraphQL ще има единична крайна точка на URL, наречена / graphql, която ще обработва всички заявки.

Копирайте следния код в server.js:

// вземете всички необходими библиотеки
const express = изисквам ('express');
const graphqlHTTP = изисквам ('express-graphql');
const {GraphQLSchema} = изисквам ('graphql');

const {queryType} = изисквам ('./ query.js');

// настройване на номера на порта и експресното приложение
const порт = 5000;
const app = express ();

 // Определете схемата
const схема = нова GraphQLSchema ({заявка: queryType});

// Настройка на nodejs GraphQL сървъра
app.use ('/ graphql', graphqlHTTP ({
    схема: схема,
    graphiql: вярно,
}));

app.listen (порт);
console.log (`GraphQL Server работи в localhost: $ {port}`);

Нека сега преминем през този код.

graphqlHTTP ни позволява да настроим GraphQL сървър на / graphql url. Той знае как да се справи с искането, което идва.

Тази настройка се извършва в следните редове от код:

app.use ('/ graphql', graphqlHTTP ({
    схема: схема,
    graphiql: вярно,
}));

Сега нека проучим параметрите в graphqlHTTP.

graphiql

graphiql е уеб интерфейс, с който можете да тествате крайните точки на GraphQL. Ще настроим това на истина, така че да е по-лесно да тестваме различните крайни точки на GraphQL, които създаваме.

схема

GraphQL има само една външна крайна точка / graphql. Тази крайна точка може да има множество други крайни точки, които правят различни неща. Тези крайни точки ще бъдат посочени в схемата.

Схемата би направила неща като:

  • Посочете крайните точки
  • Посочете входните и изходните полета за крайната точка
  • Посочете какво действие трябва да се извърши, когато е ударена крайна точка и т.н.

Схемата се дефинира както следва в кода:

const схема = нова GraphQLSchema ({заявка: queryType});

Схемата може да съдържа заявки, както и типове мутации. Тази статия ще се съсредоточи само върху типа на заявката.

запитване

Можете да видите на схемата, че заявката е зададена на queryType.

Импортираме queryType от файл query.js, използвайки следната команда:

const {queryType} = изисквам ('./ query.js');

query.js е персонализиран файл, който скоро ще създаваме.

заявката е мястото, където ние определяме крайните точки само за четене в схема.

Създайте файл, наречен като query.js в проекта и копирайте следния код в него.

const {GraphQLObjectType,
    GraphQLString
} = изисквам ('graphql');


// Определете заявката
const queryType = нов GraphQLObjectType ({
    име: „Заявка“,
    полета: {
        Здравейте: {
            тип: GraphQLString,

            разрешаване: функция () {
                връщане "Hello World";
            }
        }
    }
});

export.queryType = queryType;

запитване Обяснено

queryType се създава като GraphQLObjectType и му се дава име Query.

полетата са, където уточняваме различните крайни точки.

Така че тук добавяме една крайна точка, наречена здравей.

Здравейте има тип GraphQLString, което означава, че тази крайна точка има връщащ тип String. Типът е GraphQLString вместо String, тъй като това е GraphQL схема. Така че директно използването на String няма да работи.

функция за разрешаване показва действието, което трябва да се извърши при извикване на крайната точка. Тук действието е да се върне струнен "Hello World".

И накрая, ние експортираме querytype, използвайки export.queryType = queryType. Това е, за да се гарантира, че можем да го импортираме в server.js.

Изпълнение на приложението

Стартирайте приложението, като използвате следната команда:

възел server.js

Приложението работи на localhost: 5000 / graphql.

Можете да тествате приложението, като отидете на localhost: 5000 / graphql.

Този URL адрес изпълнява уеб интерфейса на Graphiql, както е показано на екрана по-долу.

Входът е даден вляво, а изходът е показан вдясно.

Дайте следния вход

{
  Здравейте
}

Това ще даде следния резултат

{
  "данни": {
    "здравей": "Здравей свят"
  }
}

Поздравления

Създадохте първата си крайна точка на GraphQL.

Добавяне на още крайни точки

Ще създадем 2 нови крайни точки:

  • филм: Тази крайна точка ще върне филм, като се има предвид идентификацията на филма
  • режисьор: Тази крайна точка ще върне директор, като се има предвид идентификационният номер на директора. Той също ще върне всички филми, режисирани от този режисьор.

Добавяне на данни

Обикновено приложението ще чете данни от база данни. Но за този урок, ние ще бъдем твърди за кодиране на данните в самия код за простота.

Създайте файл, наречен data.js и добавете следния код.

// Твърд код на някои данни за филми и режисьори
нека филми = [{
    id: 1,
    име: "Филм 1",
    година: 2018,
    DirectorId: 1
}
{
    id: 2,
    име: "Филм 2",
    година: 2017,
    DirectorId: 1
}
{
    id: 3,
    име: "Филм 3",
    година: 2016,
    DirectorId: 3
}
];

нека директори = [{
    id: 1,
    име: "Директор 1",
    възраст: 20
}
{
    id: 2,
    име: "Директор 2",
    възраст: 30
}
{
    id: 3,
    име: "Директор 3",
    възраст: 40
}
];

export.movies = филми;
export.directors = директори;

Този файл има данни за филмите и режисьорите. Ще използваме данните в този файл за нашите крайни точки.

Добавяне на крайната точка на филма към заявката

Новите крайни точки ще бъдат добавени към queryType във файла query.js.

Кодът за крайната точка на филма е показан по-долу:

филм: {
            тип: movieType,
            args: {
                id: {тип: GraphQLInt}
            }
            разрешаване: функция (източник, аргументи) {
                return _.find (филми, {id: args.id});
            }
        }

Типът на връщане на тази крайна точка е movieType, който ще бъде дефиниран скоро.

параметър args се използва за посочване на входа към крайната точка на филма. Входът към тази крайна точка е id, който е от тип GraphQLInt.

функция за разрешаване връща филма, съответстващ на идентификатора, от списъка с филми. find е функция от библиотеката на lodash, използвана за намиране на елемент в списък.

Пълният код за query.js е показан по-долу:

const {GraphQLObjectType,
    GraphQLString,
    GraphQLInt
} = изисквам ('graphql');
const _ = изисквам ('lodash');

const {movieType} = изисквам ('./ types.js');
нека {movies} = изискват ('./ data.js');


// Определете заявката
const queryType = нов GraphQLObjectType ({
    име: „Заявка“,
    полета: {
        Здравейте: {
            тип: GraphQLString,

            разрешаване: функция () {
                връщане "Hello World";
            }
        }

        филм: {
            тип: movieType,
            args: {
                id: {тип: GraphQLInt}
            }
            разрешаване: функция (източник, аргументи) {
                return _.find (филми, {id: args.id});
            }
        }
    }
});

export.queryType = queryType;

От горния код можем да видим, че movieType всъщност е дефиниран в types.js.

Добавяне на потребителски тип movieType

Създайте файл, наречен types.js.

Добавете следния код в type.js

const {
    GraphQLObjectType,
    GraphQLID,
    GraphQLString,
    GraphQLInt
} = изисквам ('graphql');

// Определяне на типа на филма
movieType = нов GraphQLObjectType ({
    име: „Филм“,
    полета: {
        id: {тип: GraphQLID},
        име: {тип: GraphQLString},
        година: {тип: GraphQLInt},
        DirectorId: {тип: GraphQLID}

    }
});

export.movieType = movieType;

Може да се види, че movieType е създаден като GraphQLObjectType.

Той има 4 полета: id, име, година и DirectorId. Посочват се и типовете за всяко от тези полета, докато ги добавяте.

Тези полета идват директно от данните. В този случай ще бъде от списъка с филми.

Добавяне на заявката и тип за крайната точка на директора

Подобно на филма, дори и крайната точка на режисьора може да се добави.

В query.js крайната точка на директора може да бъде добавена, както следва:

режисьор: {
            тип: DirectorType,
            args: {
                id: {тип: GraphQLInt}
            }
            разрешаване: функция (източник, аргументи) {
                return _.find (директори, {id: args.id});
            }
        }

DirectorType може да се добави, както следва, в types.js:

// Определяне на типа директор
DirectorType = нов GraphQLObjectType ({
    име: „Директор“,
    полета: {
        id: {тип: GraphQLID},
        име: {тип: GraphQLString},
        възраст: {тип: GraphQLInt},
        филми: {
            тип: нов GraphQLList (movieType),
            разрешаване (източник, аргументи) {
                return _.filter (филми, {DirectorId: source.id});
            }

        }

    }
});

Изчакайте малко. Режисьорният тип е малко по-различен от филмовия. Защо е това?

Защо има функция за разрешаване вътре в DirectorType? Преди видяхме, че функциите за разрешаване присъстват само в заявката ...

Специалният характер на режисьора Тип

Когато бъде извикана крайната точка на режисьора, трябва да върнем подробностите за режисьора, както и всички филми, които режисьорът е режисирал.

Първите 3 полета id, име, възраст в DirectorType са прави и идват директно от данните (списък на директорите).

Четвъртото поле, филми, трябва да съдържа списъка с филми от този режисьор.

За това споменаваме, че типът поле за филми е GraphQLList на movieType (Списък с филми).

Но как точно ще намерим всички филми, режисирани от този режисьор?

За това имаме функция за разрешаване във филмовото поле. Входовете към тази функция за разрешаване са източник и аргументи.

източник ще има данни за родителския обект.

Да кажем, че полетата id = 1, име = „Случайно“ и възраст = 20 за режисьор. Тогава source.id = 1, source.name = „Случайно“ и source.age = 20

Така че в този пример, функцията за разрешаване открива всички филми, в които DirectorId съответства на идентификационния номер на необходимия режисьор.

код

Целият код за това приложение е наличен в това репо за GitHub

Тестване на приложението

Сега нека тестваме приложението за различни сценарии.

Стартирайте приложението, като използвате node server.js.

Отидете на localhost: 5000 / graphql и опитайте следните входни данни.

филм

Вход:

{
  филм (id: 1) {
    име
  }
}

изход:

{
  "данни": {
    "филм": {
      "name": "Филм 1"
    }
  }
}

От горното можем да видим, че клиентът може да поиска точно това, което иска и GraphQL ще гарантира, че само тези параметри се изпращат обратно. Тук се изисква само поле за име и само това се изпраща обратно от сървъра.

Във филм (id: 1) id е входният параметър. Молим сървъра да му върне филма с идентификатор 1.

Вход:

{
  филм (id: 3) {
    име
    документ за самоличност
    година
  }
}

изход:

{
  "данни": {
    "филм": {
      "име": "Филм 3",
      "id": "3",
      "година": 2016
    }
  }
}

В горния пример са поискани полета за име, id и година. Така сървърът изпраща обратно всички тези полета.

директор

Вход:

{
  режисьор (id: 1) {
    име
    документ за самоличност,
    възраст
  }
}

изход:

{
  "данни": {
    "директор": {
      "име": "Директор 1",
      "id": "1",
      "възраст": 20
    }
  }
}

Вход:

{
  режисьор (id: 1) {
    име
    документ за самоличност,
    възраст,
    филми {
      име,
      година
    }
  }
}

изход:

{
  "данни": {
    "директор": {
      "име": "Директор 1",
      "id": "1",
      "възраст": 20,
      "филми": [
        {
          "име": "Филм 1",
          "година": 2018
        }
        {
          "име": "Филм 2",
          "година": 2017г
        }
      ]
    }
  }
}

В горния пример виждаме силата на GraphQL. Показваме, че искаме режисьор с номер 1. Също така, посочваме, че искаме всички филми от този режисьор. Както режисьорските, така и филмовите полета са адаптивни и клиентът може да поиска точно това, което иска.

По подобен начин това може да се разшири и за други полета и типове. Например, бихме могли да пуснем заявка като Намери режисьор с id 1. За този режисьор намери всички филми. За всеки от филма намерете актьорите. За всеки актьор вземете топ 5 филми с рейтинг и т.н. За тази заявка трябва да уточним връзката между типовете. След като направим това, клиентът може да запитва всяка връзка, която иска.

Поздравления

Вече знаете основните понятия на GraphQL.

Можете да разгледате документацията, за да знаете повече за GraphQL

За автора

Обичам технологиите и следя напредъка в тази област. Харесва ми и да помагам на другите с познанията си в технологиите.

Чувствайте се свободни да се свържете с мен на моя акаунт в LinkedIn https://www.linkedin.com/in/aditya1811/

Можете също да ме последвате в Twitter https://twitter.com/adityasridhar18

Моят уебсайт: https://adityasridhar.com/

Първоначално публикуван на adityasridhar.com.