Галоўная / Артыкулы / Сэмь заданняя для пачаткуюцых у програмаванні на Node.js і Express, з рашэннямі та адказамі

Сэмь заданняя для пачаткуюцых у програмаванні на Node.js і Express, з рашэннямі та адказамі

Адаптуйцеся да рашыліце сямь типавых заданняў з інтэрв’ю для пачаткуючых разработчыкаў на Node.js: ад маршрутаў Express і мідлвэра да кантролю пад час апыткаў, перакручвання строк і выяўлення дуплікат, і научыцеся адказваць на запытанні па кожным з іх.

1640 слоў

У спэцыяльныя адзінкі з Node.js і Express рэдкасцю выклікаецца патрон гэтыях алгорытмаў. Зазвычай даходзіць да короткіх заданняў, такіх як стварэнне маршруту, напісанне мідлвэра або чыстка массива, пры чым спакант разглядае, як вы мысліце і чы можаце вы поясніць, чаму ваш код працюе. Семь наведзеных нижэй заданняў охопляюць найбольш падставныя аспекты: кожна з іх мае рабочая рашэння, паследовы аналіз ключоўых частак коду і дапаможныя пункты, якія паказваюць абоўсцю разуменне тэмы.

Задання 1: Стварыце базовы маршрут GET

Класычны варыянт для розігрэву: «Створыце маршрут GET пад адресай /, які будзе вяртаць Hello World.» Рашэння заключаецца у стварэнні аплікацыі Express, рэгістрацыі обробнікага для корневай дарогі і запуску слухання на пакеце.

import express from "express";

const app = express();

app.get("/", (req, res) => {
    res.status(200).send("Hello World");
});

app.listen(3000, () => {
    console.log("Server running on port 3000");
});

Пакалькі ўжоўце import, проекту патрабуеяцца "type": "module" у файле package.json або расшырэнне .mjs.

Чытанне маршруту па лініях

Выклік app.get() рэгіструе хэндлер, які рэагуе толькі на запыты типу GET:

app.get("/", (req, res) => {

Першы аргумент, /, — гэта шлях. Калбэк прымеяць req, який описвае прыходзячы запыт, і res, які викорыстоўваецца для стварэння адпаведзення.

Сама адпаведзенне ствараецца тут:

res.status(200).send("Hello World");

status(200) задае код статусу (200 — гэта стандарт, але явная заданне ўскладнення чытаецца лепей), а send() запісвае тэла адпаведзення і завершае яго.

На заканчыце запускаецца сервер:

app.listen(3000, () => {

Эта настройка прыяжоўвае аплікэцыю да порту 3000; калебак працюе, калі сервер приймае з’яўленні. У рэальных сервісах порт зазвычай чытаецца з process.env.PORT.

Як гэта сказаць

"app.get() рэгіструе маршрут для запытаў типу GET. Калі кліент вызывае /, Express запускае калебак, які адпавядае з статусам 200 і тэкстам Hello World."

Заданне 2: Напісаць мідлвэр для логавання запытаў

Наступны праблэм: "Стварыць мідлвэр, які логавае кожны прыходзячы запыт." Мідлвэр — это функцыя з сігнатурой (req, res, next). Яна выводзіць інформацыю пра метод і URL, а пасля перадае керуванне далей; app.use() застосоўвае яго да кожнага маршруту, зарэгістрованага пасля яго.

const logger = (req, res, next) => {
    console.log(`${req.method} ${req.url}`);
    next();
};

app.use(logger);

Кожны запыт праходзіць па ланцугу мідлвэраў у порядку, прычым раней, чым обробнік маршруту адпавядае:

Client
  ↓
Request
  ↓
Logger Middleware
  ↓
Route Handler
  ↓
Response

Самая важная лінія — гэта апошня ўнутрь функцыі:

next();

next() паведамляе Express, што гэты крок завершаны і трэба запусціць наступны мідлвар або маршрут. Якщо гэта забыць, запит застаеся у стані чакання пакуль кліент не выконае таймаут, што ўсё частая пытанне. Альтернатыва — завершыць запит, адправіўшы адпаведзь, як гэта робіць мідлвар аутанацыі, калі ён адхоўчвае запит без токена.

Як гэта сказаць

"Мідлвар прыме запит, адпаведзь і next. Ён можа пераглядзець або зменіць запит, а пасля адпаведзець або вызваць next(), ўскладніўшы керуванне.

Задача 3: Керуванне асінхронной роботай у маршруце

Рэальныя канцэнтры чакаюць дадзеныя з баз дадзеных і іншых API, таму можна чакаць запытання «Як карацца з асінхроннымі операцыямі ў Express?» Яшчэ аднаго варыянта — це хандлер async з блокамі try/catch:

app.get("/users", async (req, res, next) => {
    try {
        const users = await getUsers();
        res.status(200).json(users);
    } catch (error) {
        next(error);
    }
});

Ключоўным элементам ёст await:

const users = await getUsers();

Ён зупіняе выконанне гэтага хандлера пакуль getUsers() не завершыцца, не блакаючы пры гэтым іншых запытанняў. Якщо праміс будзе адхілена, запускаецца блок catch:

catch (error) {
    next(error);
}

next(error) перадае проблему мідлвэру для обработкі адзіяў з багамі з Задання 5. Варта адзначыць, што Express 4 не перадае адхіленыя прамісы з асінхронных хандлероў, таму блаки try/catch ў такім случае є неабходныя, тады як Express 5 перадае іх аўтаматычна. Для болей шырокага разумення адзірніце як стварыць систему обработкі адзіяў з багамі рэвальнасці пры застосоўкách на Node.js.

Заданне 4: Апрэскрыць канцэнтры CRUD

CRUD — гэта Create, Read, Update і Delete, чатыры базовыя операцыі з дадзенням, кожная з яых адпрацоўвана за дапамогою адпаведнага методу HTTP. Прэтэры для рыскавання users:

app.post("/users", (req, res) => {
    res.status(201).send("User created");
});

app.get("/users", (req, res) => {
    res.status(200).send("Users");
});
app.put("/users/:id", (req, res) => {
    res.status(200).send("User updated");
});
app.delete("/users/:id", (req, res) => {
    res.status(200).send("User deleted");
});

Працэс стварэння вяртае код 201 Created, а маршруты для адзінаго корыстніка прыймаюць параметр :id, які чытаецца з req.params.id. Уместа таго, каб запамятаваць коды, трэба разумець, што означае кожны метод:

POST   → Create
GET    → Read
PUT    → Update
DELETE → Delete

Будзьце гатовыя да разліку межаў PUT і PATCH: PUT традыцыйна заменяе весь рыскавання, а PATCH прыменяе частковыя змены.

Як гэта сказаць

"CRUD аб’ёмлівае чатыры базовыя операцыі з дадзенням. У REST метод POST стварае дадзеныя, GET чытае іх, PUT або PATCH адкладае змены, а DELETE выкасывае іх."

Заданне 5: Централізаваць обработку памылак

Обработка памылак часта выконваліваецца пасля Задання 3. Пачніце з маршрута, які выдае памылку, і перадае ёю далей:

app.get("/", (req, res, next) => {
    try {
        throw new Error("Something went wrong");
    } catch (error) {
        next(error);
    }
});

Потым дадзіце працоўнік адбору памылак, які логавае і вяртае стандартны код 500:

app.use((err, req, res, next) => {
    console.error(err.message);
    res.status(500).json({
        message: "Internal Server Error"
    });
});

Тое, што робіць гэтую функцыю ўнікальной, — це яе сігнатура:

(err, req, res, next)

Express адзначае працоўнікі адбору памылак па чатырох заявленых параметрах, у порядку err, req, res, next; яны выкананы толькі калі памылка была перадана. Зарэгіструйце працоўнік пасля вашых маршрутаў і утримайцеся ад адправкі err.message кліентам у режыме продакшна. Прырода выканання:

Route
  ↓
Error occurs
  ↓
catch(error)
  ↓
next(error)
  ↓
Error middleware
  ↓
500 Response

Чы гэта неабходна — вызваць next() унутранік працоўніка адбору памылак?

Ня, якщо працоўнік сам адправляе адпаведны адказ:

app.use((err, req, res, next) => {
    console.error(err.message);
    res.status(500).send("Internal Server Error");
});

next все рава трэба заявіць, таму што пры наявнасці троха параметраў Express спрыймае гэтую функцыю як звычны мідлвэр.

Заданне 6: Адвёрнуць строчку

Дзеяныя з пытанняя ўоснованы на простам JavaScript: «Адвёрнуць строку hello.» Стандартны адпаведны код выкарыстоўвае тры методы:

const str = "hello";
const reversed = str.split("").reverse().join("");
console.log(reversed);

Ён выведае:

olleh

Што робіць кожны крок

Функцыя split дае симвалы:

str.split("")

Рэзультатам яе ёст массив:

["h", "e", "l", "l", "o"]

Потым порядак симвалав у масэве зменяецца на працоўны:

.reverse()

Гэта дае:

["o", "l", "l", "e", "h"]

У падсумку симвалы з’едынаюцца без жадных разлінавачаў:

.join("")

Гэта стварае адвёрнутую строку:

"olleh"

Паўзучы варіант: «Тепер зробіце гэта без reverse().» Цяпер трэба цікліваць ад последнаг індексу да нуля:

const str = "hello";
let reversed = "";
for (let i = str.length - 1; i >= 0; i--) {
    reversed += str[i];
}
console.log(reversed);

Оба падходы ўоснованы на лінейных операцыях. Варта згадаць, што split("") і аперацыі з індэксамі працуюць з кодавымі елементамі UTF-16, таму эмодзі розбиваюцца на часткі; [...str] замест таго робіць разлік па кодавых точках.

Заданне 7: Адказаць на дублікаты ў масе

Іншая популярная задача: «Адказаць значэнняя, якія з’являюцца больш чым раз». Дано:

const numbers = [1, 2, 3, 2, 4, 3, 5];

Адказкайце наступны рэзультат:

[2, 3]

Ўжывайце два об’екты Set: адны для значэнняя, якія вядомы, і другі для падтвердзеных дублікатаў:

const numbers = [1, 2, 3, 2, 4, 3, 5];
const seen = new Set();
const duplicates = new Set();
for (const number of numbers) {
    if (seen.has(number)) {
        duplicates.add(number);
    } else {
        seen.add(number);
    }
}
console.log([...duplicates]);

Працаванне програмы выдае:

[2, 3]

Чаму два Set работаюць

seen фіксуе кожнае значэння, яке прыносится. Першая паўтарэнне дадаецца туды:

seen.add(number);

Паўтарэнне прыводзіць да таго, што гэтыя пераказы становяцца правільнымі:

if (seen.has(number))

Значэння потым падае ў duplicates, і адколькі Set ігноруе паўтарэння, яно фіксуецца толькі раз. Пошук у такім об’екты вядзецца за майже сталякі час, таму рашэння є лінейным, а не квадратным з-за вялікага кола петляў. Чым лічыць колькісць паўтарэння, трэба ўжываць Map.

Перад тым, як пісаць, обдумайце свой падход

Найважнейшым прыкметам ёсць тое, каб вы пояснілі свой план перш чым пачаць пісаць код, таму што адзінавальнікі оцэнююць логіку так сама, як і рынкты. Для задання з дуплікатамі пачніце так:

"План — цэ ўзорк з ягоў вялікае значэнне. Пад час цыкла кожны ўжо наяўны значэнне падаецца у другі ўзорк дуплікатам, які зберагае кожны з іх унікальным."

Потым пішыце код. Гэта доказвае розумеенне працы коду, а не толькі запамятовванне, і дазволяе адзінавальніку раней скераваць вас.

Спіс пераканальных пунктав

Перш чым пройсці адзінавальнае з Node.js або Express, пераканайцеся, што вы можаце з лёгкасцю:

  • Задаць маршруты і поясніць ролі req і res
  • Выкарыстоўваць app.use() і пісаць савой мідлвэр
  • Поясніць, што робіць next() і шта выходзіць, калі яго няма
  • Керуйце асінхронным выкананнем за дапамою async/await, try/catch і next(error)
  • Запісаце працоўнік адлагоджэння бядаў з чатырма параметрамі і зарэгіструйце яго пасля маршрутаў
  • Спраявайце операцыі CRUD да методаў HTTP і адпаведных кодаў статусу
  • Маніпулюйце строкамі і масавымі даннымі за дапамою базовых методаў JavaScript
  • Выберыце між Set і Map для пошуку і пільнення
  • Опісвайце свой падход пад час напісання коду
  • На гэтым рывеньце моцныя фундаменты, чытальны код і ясныя адказы маюць набліжна большое значэнне, чым працоўныя алгорытмы.

    Спаднёе чытанне

  • Спадзячанне тыпаў часу з рэальнымі задачамі на даты: семь працаваных прыкладоў — Разберамся з семью повсякдзеннымі задачамі, якія стосуюцца дат і часу, за дапамойка JavaScript Temporal: ад простых дат і переплнення месцацяў да часовых зонаў, арыметыкі і пераканальнага контролю часу.
  • Падготовка да спытанняў на Node.js і Express: 70 пытань з точнымі адпаведзеннямі — Структураваны адгук над 70 пытаннямі, якія можуць з’явіцца на спытаннях па Node.js і Express: ад циклу запуску і стрымоў да мідлвэра, безпекі і масштабавання, з парадкамі распачатых адпаведзенняў.