FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

Merge pull request #8 from nathanKith/lab6 · islomalarov/JavaScript@effaaf8 · GitHub

Commit effaaf8

Browse files
authored
Merge pull request iu5git#8 from nathanKith/lab6
added lab6 node-js without bff
2 parents 5998c86 + e057e3e commit effaaf8

1 file changed

Lines changed: 361 additions & 0 deletions

File tree

‎tutorials/lab6/README.md‎

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
# Методические указания по выполнению лабораторной работы JavaScript
2+
3+
## План
4+
5+
1. Что такое Node.js?
6+
2. Возможности Node.js и способы применения в production-среде
7+
3. Небольшие примеры скриптов
8+
4. Пишем "голую" простую API
9+
5. Пишем API на express
10+
6. Добавляем в проект структуру (рефакторим код)
11+
7. Добавляем внешний клиент (то самое BFF)
12+
8. Что еще умеет Node.js
13+
14+
## 1. Что такое Node.js
15+
16+
Вы уже успели познакомиться с node.js в 3 лабораторной работе. но чтобы освежить в памяти вспомним снова.
17+
18+
JavaScript код, который мы пишем при обычной клиентской разработке, исполняется в браузере. В браузере у нас есть компилятор JavaScript кода в машинных код, в Google Chrome это движок [V8][v8]. Если мы хотим запускать код на нашем компьютере, а не в браузере, то нам нужно использовать [Node.js][node]. Node - это программная платформа, которая позволяет компилировать JavaScript код в машинный на нашем компьютере. На самом деле, за основу Node.js взять тот же самый движок [V8][v8]. Node.js добавляет возможность нам взаимодействовать с утройствами ввода-вывода, подключать внешние библиотеки.
19+
20+
## 2. Возможности Node.js и способы применения в production-среде
21+
22+
Писать на Node.js можно практически все: веб-сервера, десктопные и мобильные приложения, и даже программировать микроконтроллеры. В данной лабораторной работе мы остановимся на первом варианте, наиболее часто используемом, написании веб-серверов. Чаще всего на Node.js пишут именно BFF (Backend-For-Frontend), но на этом мы остановимся подробнее позже.
23+
24+
Также очень часто на Node.js пишут различные скрипты для того, чтобы автоматизировать различные процессы в инфраструктуре клиентской разработки. Например: автоматизация деплоя, различные автогенерации и тд.
25+
26+
## 3. Небольшие примеры скриптов
27+
28+
Рассмотрим несколько примеров скриптов, чтобы поподробнее посмотреть, как именно работает Node.js.
29+
30+
```ecmascript 6
31+
const {writeFileSync, readFileSync} = require('fs');
32+
const path = require('path');
33+
34+
function doMusic() {
35+
return 'listen to radiohead, guys';
36+
}
37+
38+
writeFileSync(path.join(__dirname, 'wisdom-book.txt'), doMusic());
39+
```
40+
41+
Как мы видим синтаксис идентичен синтаксису обычного javascript.
42+
В Node.js используется модульная система CommonJS. Подробнее про модульные системы можно почитать [здесь](https://habr.com/ru/company/nix/blog/261141/).
43+
44+
Еще пример:
45+
46+
```ecmascript 6
47+
const readline = require('readline');
48+
49+
const rl = readline.createInterface({
50+
input: process.stdin,
51+
output: process.stdout,
52+
terminal: false
53+
});
54+
55+
function countNumbers(str){
56+
let count = 0;
57+
for (let i = 0; i < str.length; ++i) {
58+
if (!Number.isNaN(Number.parseInt(str))) {
59+
count++;
60+
}
61+
}
62+
63+
return count;
64+
}
65+
66+
67+
rl.once('line', (line) => {
68+
console.log(countNumbers(line));
69+
70+
rl.close();
71+
});
72+
```
73+
74+
Скрипт выше принимает строку из ввода консоли и выводит сколько в ней цифр.
75+
76+
У Node.js большое число встроенных библиотек, в примере выше мы видим библиотеку `readline` для работы с вводом/выводом.
77+
В предыдущем примеры мы использовали библиотеку `fs` для работы с файловой системой.
78+
79+
## 4. Пишем "голую" простую API
80+
81+
Также в Node.js есть стандратная библиотека для написания http-серверов. Давайте ее попробуем.
82+
Создаем файл `server.js`.
83+
Подключаем библиотеку:
84+
```ecmascript 6
85+
const http = require("http");
86+
```
87+
88+
Далее в переменных объявляем на каком хосте и порте будет крутиться наш сервер.
89+
В данном случае это наш локальный адрес и 8000 порт:
90+
91+
```ecmascript 6
92+
const host = 'localhost';
93+
const port = 8000;
94+
```
95+
96+
Теперь объявим функцию, которая будет принимать запросы и отправлять ответы.
97+
У этой функции есть определенный формат: принимает два аргумента `req` - http-запрос, `res` - http-ответ.
98+
В примере внизу наш обработчик на любой запрос отдает статус `200 ОК` и в теле ответ `Курс ПСП такой крутой!`.
99+
```ecmascript 6
100+
const handler = (req, res) => {
101+
res.writeHead(200);
102+
res.end('Курс ПСП такой крутой!');
103+
};
104+
```
105+
106+
Наконец объявим сервер и заиспользуем созданные нами функцию и переменные:
107+
```ecmascript 6
108+
const server = http.createServer(handler);
109+
server.listen(port, host, () => {
110+
console.log(`Сервер запущен по адресу http://${host}:${port}`);
111+
});
112+
```
113+
114+
Итого получаем скрипт:
115+
116+
```ecmascript 6
117+
const http = require("http");
118+
119+
const host = 'localhost';
120+
const port = 8000;
121+
122+
const handler = (req, res) => {
123+
res.writeHead(200);
124+
res.end('Курс ПСП такой крутой!');
125+
};
126+
127+
const server = http.createServer(handler);
128+
server.listen(port, host, () => {
129+
console.log(`Сервер запущен по адресу http://${host}:${port}`);
130+
});
131+
```
132+
133+
Запускаем наш сервер командой:
134+
135+
```shell
136+
node server.js
137+
```
138+
139+
Видим, в консоли вывод:
140+
141+
`Сервер запущен по адресу http://localhost:8000`
142+
143+
И далее консоль зависает. В этом процессе начинает бесконечно слушать подключения наш http-сервер.
144+
Откроем новое окно консоли (не закрывая предыдущее) и пишем:
145+
146+
```shell
147+
curl http://localhost:8000
148+
```
149+
150+
И видим ответ:
151+
```shell
152+
Курс ПСП такой крутой!
153+
```
154+
155+
Поздравляю! Вы написали свой http-сервер на node.js.
156+
157+
## 5. Пишем API на express
158+
159+
В реальности на веб-серверах у нас бывает гораздо больше обработчиков,
160+
и приходится выстраивать очень сложную структуру с большим количеством бизнес-логики. Для упрощения процесса разработки написали фреймворк `express`.
161+
162+
Т.к. express это библиотека, ее необходимо устанавливать отдельно командой:
163+
164+
```shell
165+
npm i express
166+
```
167+
168+
Теперь перепишем скрипт выше и получим:
169+
170+
```ecmascript 6
171+
const express = require('express');
172+
173+
const app = express(); // 1
174+
175+
const host = 'localhost';
176+
const port = 8000;
177+
178+
const handler = (req, res) => {
179+
res.writeHead(200);
180+
res.end('ПСП такой крутой!');
181+
};
182+
183+
app.all('*', handler); // 2
184+
185+
app.listen(port, host, () => { // 3
186+
console.log(`Сервер запущен по адресу http://${host}:${port}`);
187+
});
188+
```
189+
190+
В комментарии помеченном `// 1` мы создаем приложение. Далее в `// 2` мы объявляем,
191+
что на все запросы по любому пути (путь указывается первым аргументом в определенном формате) обрабатывай
192+
с помощью функции `handler`.
193+
194+
Теперь давайте уберем помеченный обработчик `// 2` создадим побольше разных обработчиков, и потестируем их:
195+
196+
```ecmascript 6
197+
app.get('/music', (req, res) => {
198+
res.end('Я слушаю только Radiohead!');
199+
});
200+
201+
app.get('/course', (req, res) => {
202+
res.json({ course: 'ПСП' });
203+
});
204+
```
205+
206+
Теперь у нас есть 2 обработчика по 2-м разным адресам `/music` и `/course`.
207+
208+
Можем протестировать их при помощи утилиты curl и увидеть:
209+
```shell
210+
$ curl http://localhost:8000/music
211+
212+
Я слушаю только Radiohead!%
213+
214+
$ curl http://localhost:8000/course
215+
216+
{"course":"ПСП"}
217+
```
218+
219+
### API с акциями для приложения из 3-4 лабораторной работы
220+
221+
В 3 лабораторной работе в приложении давался пример, где данные возвращала функция `getData()`.
222+
Давайте вынесем отправку данных на сервер, а с клиентской части будем делать `fetch` на написанный нами сервер.
223+
224+
Создадим файл `stocks.json` рядом с `server.js`. Это будет нашей своеобразной базой-данных. Поместим туда вот эти данные:
225+
```shell
226+
[
227+
{
228+
"id": 1,
229+
"src": "https://i.pinimg.com/originals/c9/ea/65/c9ea654eb3a7398b1f702c758c1c4206.jpg",
230+
"title": "Акция",
231+
"text": "Такой акции вы еще не видели 1"
232+
},
233+
{
234+
"id": 2,
235+
"src": "https://i.pinimg.com/originals/c9/ea/65/c9ea654eb3a7398b1f702c758c1c4206.jpg",
236+
"title": "Акция",
237+
"text": "Такой акции вы еще не видели 2"
238+
},
239+
{
240+
"id": 3,
241+
"src": "https://i.pinimg.com/originals/c9/ea/65/c9ea654eb3a7398b1f702c758c1c4206.jpg",
242+
"title": "Акция",
243+
"text": "Такой акции вы еще не видели 3"
244+
}
245+
]
246+
```
247+
248+
И теперь создадим 2 обработчика: `/stocks` для получения всех акций, и `/stock/:id` для получения одной акции по ее id.
249+
250+
Чтобы читать файла напишем функцию `readJson`, которая умеет читать файл и парсить его в объект в javascript:
251+
252+
```ecmascript 6
253+
const readJson = (fileName) => {
254+
const file = fs.readFileSync(path.join(__dirname, fileName), "utf8");
255+
const json = JSON.parse(file);
256+
257+
return json;
258+
};
259+
```
260+
261+
Теперь обработчик получения всех акций:
262+
263+
```ecmascript 6
264+
const storageName = 'stocks.json';
265+
266+
app.get('/stocks', (req, res) => {
267+
const stocks = readJson(storageName);
268+
res.send(stocks);
269+
});
270+
```
271+
272+
Сначала читаем данные из файла, и затем их отдаем. Теперь напишем обработчик для получения одной акции по ее id. Здесь будет
273+
на порядок сложнее:
274+
275+
```ecmascript 6
276+
app.get('/stocks/:id', (req, res) => {
277+
const id = req.params.id; // 1
278+
279+
const numberId = Number.parseInt(id);
280+
if (Number.isNaN(numberId)) { // 2
281+
res.status(400).send({status: 'Bad Request', message: 'id must be number!'});
282+
}
283+
284+
const stocks = readJson(storageName);
285+
const stock = stocks.find((value) => { // 3
286+
return value.id === numberId;
287+
});
288+
289+
if (stock) { // 4
290+
res.send(stock);
291+
} else {
292+
res.status(404).send({status: 'Not Found', message: `not found stock with id ${numberId}`});
293+
}
294+
});
295+
```
296+
297+
В `// 1` мы достаем из url запроса параметр id. Т.е. если, например, будет сделан запрос на адрес `http://localhost:8000/stocks/2`,
298+
то `req.params.id` вернет нам 2 и тд. Название для поля `id` берет из адреса который мы указали: `/stocks/:id`. Т.е. в теории мы могли
299+
бы его поменять на что-нибудь вроде `/stocks/:stock` и доставать из запроса так `req.params.stock`.
300+
301+
Далее в `// 2` мы проверяем, что `id`, который нам передали - это число. И если нет, то отдаем ошибку со статусом 400.
302+
303+
В `// 3` мы, уже считав данные из файла, используем метод find для поиска элемента с таким id. Если такой элемент не найдется,
304+
то в переменную `stock` запишется `undefined`.
305+
306+
И уже в `// 4` проверяем смогли ли мы найти акцию с переданным `id`. Если не смогли, то отдаем ошибку с 404 статусом.
307+
308+
Весь код представлен ниже:
309+
310+
```ecmascript 6
311+
const express = require('express');
312+
313+
const app = express(); // 1
314+
315+
const host = 'localhost';
316+
const port = 8000;
317+
318+
const readJson = (fileName) => {
319+
const file = fs.readFileSync(path.join(__dirname, fileName), "utf8");
320+
const json = JSON.parse(file);
321+
322+
return json;
323+
};
324+
325+
const storageName = 'stocks.json';
326+
327+
app.get('/stocks', (req, res) => {
328+
const stocks = readJson(storageName);
329+
res.send(stocks);
330+
});
331+
332+
app.get('/stocks/:id', (req, res) => {
333+
const id = req.params.id;
334+
const numberId = Number.parseInt(id);
335+
336+
if (Number.isNaN(numberId)) {
337+
res.status(400).send({status: 'Bad Request', message: 'id must be number!'});
338+
}
339+
340+
const stocks = readJson(storageName);
341+
const stock = stocks.find((value) => {
342+
return value.id === numberId;
343+
});
344+
345+
if (stock) {
346+
res.send(stock);
347+
} else {
348+
res.status(404).send({status: 'Not Found', message: `not found stock with id ${numberId}`});
349+
}
350+
});
351+
352+
app.listen(port, host, () => { // 3
353+
console.log(`Сервер запущен по адресу http://${host}:${port}`);
354+
});
355+
```
356+
357+
## 6. Добавляем в проект структуру (рефакторим код)
358+
359+
## 7. Добавляем внешний клиент (то самое BFF)
360+
361+
## 8. Что еще умеет Node.js

0 commit comments

Comments
 (0)

Back | FazBrowse Home | New Git URL