В этом руководстве мы узнаем, как создать Rest API в Node.js и Express.js, создав простой API приложения todo. В этом руководстве предполагается наличие среднего уровня знаний JavaScript и опыта работы с командной строкой. Исходный код финального проекта можно найти здесь.
Начало работы
Для начала создайте новую папку и назовите ее todo.
$ mkdir todo $ cd todo
В папке с задачами создайте новый файл с именем app.js
$ touch app.js
Следующее, что нам нужно сделать, это установить Node. вы можете установить узел здесь. После установки узла мы установим экспресс с помощью npm. Node поставляется с npm, поэтому нам не нужно устанавливать npm.
Инициализировать приложение
Перейдите в командной строке к корню вашего приложения и запустите.
npm init
Повторно нажимайте клавишу возврата для каждого вопроса, который вам задают в командной строке.
Это создаст для вас файл package.json.
Установите зависимости и настройте Babel
$ npm install express —-save
Нам также потребуется установить babel, потому что мы будем писать синтаксис ES6, Babel помогает превратить наши коды с ES6 в ES5. почему мы должны компилировать наш код до ES5? Что ж, есть некоторые функции ES6, которые наши браузеры и узел еще не понимают, а старые браузеры не понимают коды ES6, поэтому мы используем babel для компиляции нашего кода в ES5, чтобы его могли понять как старые браузеры, так и новые браузеры. Наша цель использования babel здесь состоит в том, чтобы функции ES6, которые еще не являются частью узла, могли быть скомпилированы до ES5, который понимает узел.
$ npm install babel-cli --save
Мы также будем устанавливать babel-preset-es2015, пресеты содержат набор плагинов, эти плагины предназначены для функций ES6, установив и настроив babel-preset-es2015, мы сообщаем babel, что нужно преобразовать любые функции ES6, которые мы используем, которые содержатся в предустановки к их эквиваленту ES5.
$ npm install babel-preset-es2015 --save
Теперь нам нужно создать файл .babelrc, в файле babelrc мы настроим babel на использование предустановки es2015, которую мы установили в качестве предустановки при компиляции в ES5.
В корне нашего приложения мы создадим файл .babelrc.
$ touch .babelrc
В файле babelrc введите следующее, чтобы настроить предустановку.
{
"presets": ["es2015"]
}
Это говорит babel использовать es2015 в качестве предустановки, обратите внимание, что ES2015 - это другое имя для ES6.
Создать фиктивную базу данных
Последнее, что нам нужно сделать, прежде чем мы начнем создавать наш Apis, - это создать фиктивную базу данных, которую мы будем использовать.
Создайте папку и назовите ее db.
$ mkdir db
В папке создайте файл и назовите его db.js
$ cd db $ touch db.js
В db.js создайте объект javascript для создания фиктивной базы данных
const todos = [
{
id: 1,
title: "lunch",
description: "Go for lunc by 2pm"
}
];
export default todos;
Настройте приложение и создайте нашу первую конечную точку
А теперь приступим к созданию нашего приложения.
import express from 'express';
import db from './db/db';
// Set up the express app
const app = express();
// get all todos
app.get('/api/v1/todos', (req, res) => {
res.status(200).send({
success: 'true',
message: 'todos retrieved successfully',
todos: db
})
});
const PORT = 5000;
app.listen(PORT, () => {
console.log(`server running on port ${PORT}`)
});
Мы импортировали экспресс, который мы установили в начале курса, app.get делает запрос на получение на сервер с маршрутом / конечной точкой, предоставленной в качестве первого параметра, конечная точка предназначена для возврата всех задач в базе данных. Второй параметр - это функция, которая запускается каждый раз, когда мы достигаем этой конечной точки. функция принимает два параметра: req и res. Объект req содержит информацию о нашем запросе, а объект ответа содержит информацию об ответе и методах, которые мы можем использовать для отправки информации обратно клиенту.
res.status (200) используется для отправки статуса запроса, 200 означает ОК и указывает на успешный запрос. Коды состояния - это способы, с помощью которых клиент, например веб-приложение или мобильное приложение, может проверить, пошло ли что-то не так. действительно заинтересованы. Если возвращается 200, мы можем проверить полезную нагрузку, потому что знаем, что чего-то ожидаем. Подробнее о кодах статуса HTTP можно узнать здесь.
res.send () используется для отправки ответа клиенту, ресурс, переданный в send в качестве параметра, - это то, что отправляется обратно клиенту. в этом случае мы отправляем обратно объект, который содержит некоторую информацию, свойство todos объекта содержит данные, которые мы импортировали в верхней части app.js из нашей фиктивной базы данных.
app.listen создает для нас веб-сервер, он принимает два параметра, первый параметр - это порт, который мы хотим, чтобы наше приложение прослушивало t, независимо от того, какой порт мы предоставляем, в нашем случае 5000 будет порт, на котором будет работать наш сервер в нашей системе. второй параметр является необязательным, это функция обратного вызова того, что должно произойти при создании сервера, в нашем случае мы записываем сообщение в консоль. когда сервер будет создан, мы сможем получить доступ к нашей конечной точке ’/ api / v1 / todos’ оттуда. сервер будет работать на порту 5000 на локальном хосте на нашей машине. так что у нас будет наш маршрут localhost: port / api. Созданная нами конечная точка будет доступна следующим образом: localhost: 5000 / api / v1 / todos.
Теперь, чтобы запустить этот код, перейдем к командной строке. Обычно мы запускаем наше приложение узла из командной строки, как это.
$ node app.js
Но это вызовет ошибку, потому что наш код находится на ES6, и для успешного выполнения нашего кода нам нужно будет запустить его с помощью babel-node, который скомпилирует его в ES5. babel-node поставляется с babel-cli, которое мы установили в начале курса.
$ node_modules/.bin/babel-node app.js
Теперь мы можем пойти к почтальону и протестировать нашу конечную точку, почтальон - это приложение, которое мы используем для тестирования наших конечных точек. скачать почтальона можно здесь.
Чтобы протестировать конечную точку, мы перейдем на localhost: 5000 / api / v1 / todos.

Взгляните на «GET» перед localhost: 5000 / api / v1 / todos, помните, что наша конечная точка - это запрос на получение, поэтому мы установили этот раскрывающийся список на «GET», если наша конечная точка была почтовым запросом, то есть у нас было приложение. post, тогда мы бы установили для него POST.
Запускать наш сервер, запуская это каждый раз, сложно, чтобы упростить этот процесс, мы собираемся сделать две вещи: во-первых, мы собираемся установить nodemon, во-вторых, мы создадим скрипт в нашем пакете, json, чтобы запустить наш сервер.
Давайте установим nodemon, запустите в своем терминале следующее.
$ npm install nodemon --save-dev
Nodemon следит за вашим приложением на предмет изменений файлов и перезапускает сервер каждый раз, когда файл изменяется в вашем приложении. Это упрощает вашу работу, потому что вам не нужно запускать и перезапускать сервер вручную каждый раз, когда вы меняете файлы в приложении.
Давайте создадим скрипт в вашем package.json внутри части скрипта, включая это
"start": "node_modules/.bin/nodemon app.js --exec babel-node --"
Вы знаете, что делает babel-node.
Ваши скрипты package.json должны выглядеть так
{
"name": "todo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"start": "nodemon app.js --exec babel-node --"
},
"author": "",
"license": "ISC",
"dependencies": {
"babel-cli": "^6.26.0",
"babel-preset-es2015": "^6.24.1"
"express": "^4.16.3"
}
}
Теперь каждый раз, когда мы хотим запустить наше приложение, мы просто запускаем следующий скрипт на терминале.
npm run start
Это запустит стартовый скрипт в нашем файле package.json.
Давайте создадим конечную точку для добавления задач, но перед этим давайте установим пакет под названием body-parser, body-parser анализирует тела входящих запросов в промежуточном программном обеспечении перед вашими обработчиками, доступными в req.bodyproperty.
Когда вы отправляете данные на сервер, данные могут поступать из формы или это может быть json, парсер тела анализирует эти данные, поступающие от клиента, в объекте с именем req.body, поэтому для Например, если у меня есть данные JSON, поступающие от клиента на сервер.
{
"name": "Ola",
"school": "unilag"
}
Что делает парсер тела, так это то, что он анализирует эти данные JSON и делает их доступными в req.body как свойство. помните, что req - это первое свойство, которое мы предоставляем для нашего обратного вызова, когда мы делаем запрос API, и помните, что я сказал, что req содержит информацию о запросе, исходящем от клиента, поэтому парсер тела делает данные, поступающие из формы, или любые данные JSON, поступающие от клиента, доступного как свойство в req.body, поэтому мы можем получить доступ к данным JSON из req.body как.
req.body.name req.body.school
Итак, давайте установим body-parser
$ npm install body-parser --save
Теперь давайте импортируем его в app.js
import bodyParser from 'body-parser';
Теперь мы настроим парсер тела для нашего приложения вот так.
const app = express();
// Parse incoming requests data
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
Создать Todo
Теперь перейдем к созданию конечной точки для создания задачи.
app.post('/api/v1/todos', (req, res) => {
if(!req.body.title) {
return res.status(400).send({
success: 'false',
message: 'title is required'
});
} else if(!req.body.description) {
return res.status(400).send({
success: 'false',
message: 'description is required'
});
}
const todo = {
id: db.length + 1,
title: req.body.title,
description: req.body.description
}
db.push(todo);
return res.status(201).send({
success: 'true',
message: 'todo added successfully',
todo
})
});
В этой конечной точке мы не делаем запрос к серверу для получения данных, а скорее отправляем данные. как мы объяснили, входящие данные анализируются в req.body как свойства, поэтому у нас есть req. body.title и т. д.
Мы создаем объект todo с информацией, которую мы получили от клиента через body-parser, а затем помещаем его в фиктивный массив db в качестве нового todo.
Давайте проверим это в почтальоне, нам нужно будет передать некоторые данные и отправить их на сервер, чтобы проверить это, на почтальоне, когда вы выбираете POST, щелкните тело n перед заголовками, которые находятся перед авторизацией, и передайте свои значения в поле.
localhost: 5000 / api / v1 / todos, убедитесь, что вы установили HTTP-метод в почтальоне на POST.

Взгляните на 'POST' перед localhost: 5000 / api / v1 / todos, помните, что наша конечная точка - это почтовый запрос, поэтому мы установили этот раскрывающийся список на POST. Убедитесь, что переключатель x-www-form-urlencoded установлен или используйте raw, где вы передаете данные JSON, как это.
{
"title": "breakfast",
"description": "get breakfast"
}
Получите одно задание
Теперь давайте создадим конечную точку, чтобы получить одно задание из базы данных. Введите следующее:
app.get('/api/v1/todos/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
db.map((todo) => {
if (todo.id === id) {
return res.status(200).send({
success: 'true',
message: 'todo retrieved successfully',
todo,
});
}
});
return res.status(404).send({
success: 'false',
message: 'todo does not exist',
});
});
Как обычно, эта конечная точка принимает два параметра: маршрут и функцию обратного вызова. Другое дело, что маршрут в этой конечной точке имеет: id, иногда мы хотим передать параметры нашим конечным точкам, потому что они потребуются нам в нашем приложении, чтобы передать те параметры, которые мы используем: param.
Конечная точка, созданная выше, предназначена для получения одного задания, для получения одного задания нам понадобится уникальный способ идентифицировать это задание в базе данных, поэтому, если мы знаем идентификатор задания, которое мы хотим получить, мы можем затем его получить. из базы данных, поэтому каждый раз, когда мы делаем запрос к этой конечной точке, мы передаем идентификатор задачи, которую хотим получить, функция обратного вызова затем запросит базу данных для задачи с этим приложением.
Что происходит в конечной точке выше, так это то, что мы передаем идентификатор задачи, которую хотим получить в качестве параметра для маршрута, чтобы получить значение идентификатора, переданное в маршрут, который мы используем req.params.id, req.params - это объект, который содержит все параметры, переданные маршрутам, мы преобразуем идентификатор в int, а затем мы перебираем нашу фиктивную базу данных db, чтобы найти задачу, идентификатор которой будет равен тому, который мы получили из URL-адреса, тогда соответствующая задача будет вернулся как единственное задание.
Давайте проверим это, возьмем общее количество задач в базе данных, чтобы увидеть, что у нас есть на данный момент.

Теперь давайте добавим новую задачу в базу данных.

Давайте снова получим все задачи из базы данных

Теперь у нас есть новое задание, которое мы только что добавили в базу данных.
Давайте теперь протестируем нашу конечную точку, перейдите по адресу localhost: 5000 / api / v1 / todos /: id, замените: id на идентификатор задачи, которую вы хотите получить. в нашем случае задача с идентификатором 2, установите для метода http значение GET.

Удалить Todo
Теперь давайте создадим конечную точку для удаления задач из базы данных.
app.delete('/api/v1/todos/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
db.map((todo, index) => {
if (todo.id === id) {
db.splice(index, 1);
return res.status(200).send({
success: 'true',
message: 'Todo deleted successfuly',
});
}
});
return res.status(404).send({
success: 'false',
message: 'todo not found',
});
});
Так что мы здесь делаем? ну, в основном мы передаем id задачи, которую хотим удалить, в качестве параметра route / api / v1 / todos /: id. мы получаем этот идентификатор с помощью req.params.id, поэтому, чтобы удалить элемент с этим идентификатором, мы должны сначала найти его в базе данных, мы сделали это, сопоставив массив db и проверив идентификатор текущего дела в итерация по идентификатору, полученному из маршрута, пока мы не найдем совпадение, затем мы используем метод массива splice (), чтобы удалить этот элемент из базы данных. Вы можете узнать больше о array.splice и о том, как он работает здесь. В случае, если мы ничего не находим, мы возвращаем пользователю сообщение todo not found.
Теперь давайте проверим это, сначала давайте извлечем задачи из нашей базы данных, чтобы увидеть, что у нас есть.

Теперь давайте добавим новую задачу

давай снова принесем все наши задачи

Как вы можете видеть, теперь у нас есть два задачи в нашей базе данных, предыдущая, которая была там изначально (мы жестко запрограммировали это в приложении), - это задача с идентификатором 1, а новая, которую мы добавили, - это задача с идентификатором. из 2.
Теперь давайте удалим задачу с идентификатором 1, перейдя к только что созданной конечной точке. Перейдите к localhost: 5000 / api / v1 / todos /: id, id в этом случае 1, просто замените: id на 1 в конечной точке.

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

Теперь у нас есть только задача с идентификатором 2.
Давайте попробуем удалить Todo с несуществующим идентификатором.

Мы получаем сообщение, что задача не найдена.
Обновить Todo
Теперь давайте создадим конечную точку для обновления задач.
app.put('/api/v1/todos/:id', (req, res) => {
const id = parseInt(req.params.id, 10);
let todoFound;
let itemIndex;
db.map((todo, index) => {
if (todo.id === id) {
todoFound = todo;
itemIndex = index;
}
});
if (!todoFound) {
return res.status(404).send({
success: 'false',
message: 'todo not found',
});
}
if (!req.body.title) {
return res.status(400).send({
success: 'false',
message: 'title is required',
});
} else if (!req.body.description) {
return res.status(400).send({
success: 'false',
message: 'description is required',
});
}
const updatedTodo = {
id: todoFound.id,
title: req.body.title || todoFound.title,
description: req.body.description || todoFound.description,
};
db.splice(itemIndex, 1, updatedTodo);
return res.status(201).send({
success: 'true',
message: 'todo added successfully',
updatedTodo,
});
});
Как обычно, мы получаем идентификатор задачи, которую хотим обновить, из URL-адреса, мы перебираем нашу фиктивную базу данных, чтобы найти задачу с этим идентификатором, если мы не находим задачу, мы возвращаем сообщение пользователю с указанием задачи не найден. Если мы находим задачу, мы получаем новый ввод, предоставленный пользователем, новый ввод анализируется парсером тела в req.body, мы получаем обновленные записи из req.body и создаем с ним обновленный объект задачи. Затем мы используем db.splice, чтобы удалить старый todo, который соответствует нашей итерации, когда мы перебирали фиктивный db, и заменяем его на updatedTodo, который мы создали.
Давай проверим это.
Давайте возьмем все задачи, которые есть в нашей базе данных в настоящее время. Обратите внимание, что каждый раз, когда ваш сервер перезагружается, вы теряете записи, которые у вас есть в памяти, поэтому мы теряем задачу, которую мы добавили через почтальона, когда наш сервер перезагружается, за исключением того, который мы жестко запрограммировали в приложении. .

Теперь давайте обновим задачу с идентификатором 1.

Мы подошли к концу этого урока, есть вторая часть этого урока, и вы можете найти ее здесь. Спасибо за ваше время и терпение, чтобы пройти через это, и я очень надеюсь, что вы узнали одну или две вещи.