Russian (Pусский) translation by Liliya (you can also view the original English article)

AWS Amplify позволяет разработчикам быстро создавать и подключаться к мощным сервисам в облаке. В предыдущем уроке вы узнали, как настроить Amplify в проекте React и как использовать аутентификацию, хранилище S3 и хостинг. Если вам нужно введение в AWS Amplify, сначала ознакомьтесь с этим постом.
В этом посте мы продолжим работу с React и AWS Amplify, исследуя такие функции, как управляемый уровень данных GraphQL и лямбда-функции.
Добавление API GraphQL
Давайте посмотрим, как добавить AWS AppSync GraphQL API в наш проект и начать использовать его из нашего проекта.
API, который мы создадим, будет ресторанным API для нас, чтобы идти в ногу с ресторанами, которые мы хотели бы или хотели бы посетить.
Чтобы добавить GraphQL API в наш проект, мы можем использовать следующую команду:
amplify add api
Вам будет предложено ответить на некоторые вопросы конфигурации. Выберите следующие параметры:
- Тип сервиса: GraphQL
- Имя API: TutsGraphQLAPI
- тип авторизации: ключ API
- аннотированная схема GraphQL: N
- создание управляемой схемы: Y
- Что лучше всего описывает ваш проект? Один объект с полями (например, «Todo» с идентификатором, именем, описанием)
- Вы хотите изменить схему сейчас? Y
При появлении запроса обновите схему до следующего, а затем сохраните файл:
// located at amplify-web-app/amplify/backend/api/TutsGraphQLAPI/schema.graphql type Restaurant @model { id: ID! name: String! description: String }
Это просто создает один тип данных - Restaurant
- с обязательными полями id и именем, а также необязательным описанием.
Затем давайте обновим нашу учетную запись:
amplify push
Теперь API создан!
Что здесь только что произошло? AWS Amplify использовала встроенную библиотеку GraphQL Transform для создания полного API-интерфейса GraphQL, включая дополнительную схему, преобразователи и источник данных.
Чтобы просмотреть новый API AppSync AWS в любое время после ее создания, вы можете перейти в панель управления на https://console.aws.amazon.com/appsync и нажмите на API, который был только что создан (убедитесь, что ваш регион установлен правильно). От в пределах AWS AppSync приборной панели, можно просматривать API конфигурации и выполнять запросы и мутации на API.
Выполнение мутаций GraphQL
Далее давайте взаимодействуем с API из нашего приложения React.
Первое, что мы хотели бы сделать, это создать мутацию. В GraphQL мутации являются эквивалентом операций REST PUT
, PUSH
и DELETE
. Поскольку в нашей базе данных еще нет данных, мы создадим мутацию для создания нового элемента ресторана.
Для этого мы импортируем API
и graphqlOperation
из AWS Amplify, определяем мутацию и затем выполняем ее.
Давайте рассмотрим пример приложения, которое реализует мутацию. В App.js
сначала импортируем React, наше приложение CSS и необходимые компоненты AWS Amplify.
import React, { Component } from 'react'; import './App.css'; import { withAuthenticator } from 'aws-amplify-react' import { API, graphqlOperation } from 'aws-amplify'
Далее мы определяем мутацию для создания ресторана. Мы указываем, что мутация принимает имя и описание и называется createRestaurant
. Эта мутация была определена автоматически, когда мы создали схему Restaurant
выше. Обратите внимание, что мутация указана в GraphQL - доменном языке запросов.
const CreateRestaurant = ` mutation($name: String!, $description: String) { createRestaurant(input: { name: $name description: $description }) { id name description } } `
Теперь мы создаем наш компонент приложения.
class App extends Component { //create initial state state = {name: '', description: ''} //update state when user types into inputs onChange = e => { this.setState({ [e.target.name]: e.target.value }) } //define function to execute mutation //render the component }
Далее, все еще в компоненте App
, мы определяем функцию для выполнения мутации. Это выполняет мутацию путем вызова API.graphql
, передавая мутацию и данные.
//define function to execute mutation createRestaurant = async() => { if (this.state.name === '' || this.state.description === '') return try { const restaurant = { name: this.state.name, description: this.state.description } await API.graphql(graphqlOperation(CreateRestaurant, restaurant)) this.setState({ name: '', description: '' }) console.log('restaurant successfully created!') } catch (err) { console.log('error creating restaurant...') } }
Затем мы визуализируем компонент, связывая наш обработчик изменений и функции мутации.
//render the component render() { return ( <div className="App"> <input value={this.state.name} onChange={this.onChange} name='name' /> <input value={this.state.description} onChange={this.onChange} name='description' /> <button onClick={this.createRestaurant}>Create Restaurant</button> </div> ) }
Наконец, мы экспортируем компонент App
с аутентификацией.
export default withAuthenticator(App, { includeGreetings: true });
Вы должны быть в состоянии запустить этот код и начать создавать новые элементы ресторана в API.
Чтобы просмотреть фактический источник данных, чтобы увидеть, есть ли данные, откройте панель инструментов AWS AppSync, выберите свой API, нажмите Data Sources в левом меню, а затем нажмите Resource Name. Откроется таблица Amazon DynamoDB. В таблице вы можете просмотреть данные на вкладке Items.
Выполнение запросов GraphQL
Далее давайте посмотрим, как запрашивать данные из API. Мы реализуем это в три этапа:
- определить запрос
- выполнить запрос, когда приложение загружается
- сохранить результат запроса в нашем состоянии и отобразить его в пользовательском интерфейсе.
Сначала давайте определим запрос в новом компоненте. Еще раз, мы используем язык GraphQL для определения запроса. Мы используем запрос listRestaurants
, который был автоматически определен при нажатии на схему Restaurants
. Фрагмент ниже указывает, что мы ожидаем список элементов, каждый с идентификатором, именем и описанием.
const ListRestaurants = ` query { listRestaurants { items { id name description } } }
Далее нам нужно добавить дополнительное начальное состояние для хранения массива ресторанов, возвращаемых с сервера.
state = { name: '', description: '', restaurants: [] }
Нам также нужно добавить событие жизненного цикла componentDidMount
для запроса данных с сервера GraphQL. Этот асинхронный метод обновит состояние компонента при возврате списка ресторанов с сервера.
async componentDidMount() { try { const restaurants = await API.graphql(graphqlOperation(ListRestaurants)) console.log('restaurants: ', restaurants) this.setState({ restaurants: restaurants.data.listRestaurants.items }) } catch (err) { console.log('error fetching data: ', err) } }
Наконец, мы создадим компонент, который отображает массив ресторанов
из состояния компонента в HTML.
{ this.state.restaurants.map((r, i) => ( <div key={i}> <p>{r.name}</p> <p>{r.description}</p> </div> )) }
Теперь, когда мы запустим приложение, мы увидим, что данные из API отображаются в виде списка на экране. Тем не менее, приложение не будет отображать никаких изменений при обновлении данных, например, при добавлении нового ресторана.
Для начала давайте обновим метод createRestaurant
, чтобы обеспечить оптимистичный ответ на пользовательский интерфейс. Прямо сейчас, когда мы создаем новый элемент, база данных обновляется, но пользовательский интерфейс еще не знает о новом элементе. Чтобы это исправить, мы обновим массив restaurant в методе createRestaurant
, добавив новый элемент в массив:
createRestaurant = async() => { if (this.state.name === '' || this.state.description === '') return try { const restaurant = { name: this.state.name, description: this.state.description } const restaurants = [...this.state.restaurants, restaurant] this.setState({ name: '', description: '', restaurants }) await API.graphql(graphqlOperation(CreateRestaurant, restaurant)) console.log('restaurant successfully created!') } catch (err) { console.log('error creating restaurant...') } }
Подписки на данные в реальном времени
Далее мы хотим иметь возможность работать с данными в реальном времени. В GraphQL подписки позволяют прослушивать данные в режиме реального времени. Когда новые данные доступны, подписка запускается, и новые данные передаются через подписку. На стороне клиента мы должны обработать эти новые данные.
В нашем приложении мы подпишемся на множество ресторанов и создадим подписку onCreateRestaurant
, которая будет срабатывать при каждом создании нового ресторана. Затем мы возьмем новый элемент из подписки, обновим наш существующий массив и вызовем setState
для повторной визуализации интерфейса с новыми данными.
Как и для мутаций и запросов, мы начнем с определения подписки на доменном языке GraphQL.
// define the subscription const OnCreateRestaurant = ` subscription { onCreateRestaurant { id name description } } `
Подписка будет создана в методе жизненного цикла componentDidMount
либо до, либо после запроса GraphQL, который мы уже настроили:
async componentDidMount() { try { const restaurants = await API.graphql(graphqlOperation(ListRestaurants)) console.log('restaurants: ', restaurants) this.setState({ restaurants: restaurants.data.listRestaurants.items }) } catch (err) { console.log('error fetching data: ', err) } API.graphql(graphqlOperation(OnCreateRestaurant)) .subscribe({ next: eventData => { const data = eventData.value.data.onCreateRestaurant console.log('data: ', data) const restaurants = [ ...this.state.restaurants.filter(r => r.name !== data.name && r.description !== data.description), data ] this.setState({ restaurants }) } }) }
Теперь, если вы откроете два окна браузера, вы сможете создать мутацию на одном экране и увидеть, как происходит обновление на всех других экранах.
Если вы посмотрите на метод .filter
, который мы использовали при создании нового массива ресторанов в подписке, вы увидите, что мы проверяем, есть ли дубликаты, которые содержат и то же имя и описание. Возможно, лучшим способом сделать это в производственной среде было бы создание уникального идентификатора клиента, который также хранится в базе данных, и фильтрация на основе этого идентификатора.
Создание API REST с помощью AWS Lambda
GraphQL - замечательная передовая технология, но иногда наш проект требует, чтобы мы создали традиционный REST API. С помощью AWS Lambda и Amplify также легко создавать безсерверные REST API с помощью CLI.
Когда мы создавали GraphQL API, мы использовали команду ampify create api
. Эта команда дает нам возможность создания API-интерфейса GraphQL или REST API. API REST можно настроить для использования либо автономной функции Express без сервера, либо функции JavaScript без сервера, которая предварительно настроена для работы с CRUD-операциями Amazon DynamoDB.
Опция, которую мы будем использовать для этого API, - это безсерверная функция Express.
Давайте продолжим и добавим новую функцию:
amplify add api
Как обычно, это побудит вас заполнить некоторые детали конфигурации. Поставьте следующие варианты:
- Тип сервиса: REST
- введите имя ресурса, которое будет использоваться в проекте: amplifyrestapi
- введите путь для конечных точек REST: например, /люди
- Источник Lambda: создайте новую функцию лямбда
- AWS Название функции Lambda: amplifyrestapifunction
- шаблон функции: Бессерверная экспресс-функция (интеграция с Amazon API Gateway)
- редактировать локальную лямбда-функцию сейчас? Y
Теперь вы сможете редактировать лямбда-функцию локально. В этом файле мы заменим существующий метод app.get ('/ people')
следующим:
// amplify-web-app/amplify/backend/function/amplifyrestapi/src/app.js app.get('/people', function(req, res) { const people = [ { name: "Nader" }, { name: "Amanda" }, { name: "Chris" }, { name: "" } ] res.json({ success: true, people }) });
Это просто возвращает постоянный список имен для демонстрационных целей. Сохраните этот файл и продолжайте со следующими ответами:
- ограничить доступ к API? да
- у кого должен быть доступ? Только аутентифицированные пользователи
- какой доступ вы хотите для аутентифицированных пользователей? read
- добавить еще один путь? N
Это создало новую функцию Lambda локально, которую мы сможем обновлять и добавлять в нашу учетную запись по мере необходимости. Код для этой лямбда-функции находится по адресу ampify/backend/function/ampifyrestapi/src.
Теперь давайте загрузим обновления в наш аккаунт:
amplify push
Запрос API REST от клиента
Теперь наша функция Lambda запущена, и мы можем начать с ней взаимодействовать!
Сначала давайте запросим данные из нового API и покажем их в нашем пользовательском интерфейсе. Для этого мы будем использовать класс API от Amplify, вызывая API.get
. В предыдущем разделе мы использовали API.graphql
для отправки запросов к нашему API GraphQL, но в классе API доступно много методов. Вы можете узнать больше о классе API в официальных документах.
import { API } from 'aws-amplify' // 1. in the initial state, create an empty array of people state = { people: [] } // 2. in componentDidMount, we will fetch this data using the API class try { const peopleData = await API.get('amplifyrestapi', '/people') this.setState({ people: peopleData.people }) } catch (err) { console.log('error fetching from Lambda API') } // 3. render the people data to the UI in the render method { this.state.people.map((person, index) => ( <p key={index}>{person.name}</p> )) }
Теперь мы должны иметь возможность запустить приложение, получить данные о людях из нашего API и отобразить их на экране.
Обновление лямбда-функции из CLI
Помимо создания новой функции Lambda, мы также можем обновить нашу функцию Lambda из CLI.
Давайте изменим функцию так, чтобы она обращалась к API и получала данные вместо констант жесткого кодирования. Для этого мы будем использовать библиотеку axios для выполнения HTTP-запросов и получать данные из Star Wars API.
Чтобы использовать axios, нам нужно перейти к amplify/backend/function/amplifyrestapi/src и установить его там. Axios установлен в папке проекта функции Lambda, а не в главной папке приложения, потому что он будет работать на стороне сервера функции Lambda.
yarn add axios # or npm install axios
Теперь, когда axios установлен, мы обновим функцию Lambda для получения данных из Star Wars API:
var axios = require('axios') app.get('/people', function(req, res) { axios.get('https://swapi.co/api/people/') .then(response => { res.json({ success: true, people: response.data.results }) }) .catch(error => { res.json({ success: false, error }) }) });
Теперь сохраните файл и выполните команду ampify push
из основной папки проекта, чтобы обновить функцию Lambda в облаке:
amplify push
Теперь наш API обновлен и готов к работе!
Когда мы обновляем приложение, мы должны увидеть данные, которые возвращаются из Star Wars API.
Заключение
Из этой серии вы узнали, как начать работу с AWS Amplify и добавить его в свой проект React, а также как добавить аутентификацию, хранилище, хостинг и API-интерфейс GraphQL или REST - и все это без необходимости вручную кодировать или выделять сервер. Это большая сила для разработчиков приложений!
Я надеюсь, что эти посты вдохновили вас на создание ваших собственных серверных веб-приложений с использованием безсерверной технологии и AWS Amplify! Дайте нам знать, что вы думаете в комментариях ниже.
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Update me weeklyEnvato Tuts+ tutorials are translated into other languages by our community members—you can be involved too!
Translate this post