Middleware đầu tiên của bạn
Thuộc phần Kiến thức cơ bản về Express trong hành trình Node.js của Coddy. Bài học 13 trên 23.
Mỗi yêu cầu đều có những việc cần thực hiện, chẳng hạn như ghi một dòng vào nhật ký. Sao chép việc đó vào từng tuyến xử lý sẽ không bao giờ xong. Mỗi yêu cầu đều có một phương thức, trong req.method: GET để lấy nội dung nào đó, POST để gửi nội dung nào đó.
let visits = 0;
app.use((req, res, next) => {
visits++;
next();
});Hàm (function) truyền cho app.use là phần mềm trung gian (middleware): Express chạy hàm này cho mọi yêu cầu, theo thứ tự được thêm vào, trước các tuyến xử lý bên dưới. Hàm nhận tham số thứ ba là next. Gọi next() sẽ chuyển yêu cầu đến phần tiếp theo. Phần mềm trung gian không trả lời cũng không gọi next() sẽ khiến yêu cầu chờ mãi.
express.static trong chương trước cũng là phần mềm trung gian: nó trả lời khi tìm thấy tệp và gọi next() khi không tìm thấy.
Thử thách
DễBạn muốn ghi lại một dòng nhật ký cho mỗi yêu cầu mà máy chủ nhận được, để biết khách truy cập yêu cầu những gì.
- Trong
server.js, ngay sauconst app = express();, thêm một middleware bằngapp.use. Đặt middleware ở đó để nó chạy trước mọi tuyến. - Với mỗi yêu cầu, middleware in ra một dòng trong Console: phương thức của yêu cầu, một dấu cách, rồi đến đường dẫn. Yêu cầu đến
/recipes/2sẽ in raGET /recipes/2. Phương thức nằm trongreq.method(GET,POSTvà các phương thức khác), còn đường dẫn nằm trongreq.url. - Sau khi in ra, middleware gọi
next(), để yêu cầu tiếp tục đi đến các tuyến.
Thử nhé: Nhấn Chạy rồi gửi yêu cầu đến /recipes/2. Bạn sẽ thấy Pancakes, còn Console hiển thị GET /recipes/2. Gửi yêu cầu đến /api/recipes: danh sách như thường lệ, và GET /api/recipes trong Console. Gửi yêu cầu đến /nope: nhận lỗi 404, còn Console vẫn hiển thị GET /nope, vì middleware chạy trước khi Express tìm tuyến phù hợp.
Tự làm thử
import { escapeHtml } from './html.js';
import express from 'express';
import { recipes } from './data.js';
const app = express();
app.use(express.static('public'));
app.get('/', (req, res) => {
const items = recipes.map((r) => `<li><a href="/recipes/${r.id}">${escapeHtml(r.title)}</a></li>`);
res.send(`<link rel="stylesheet" href="/style.css"><h1>Recipe Box</h1><ul>${items.join('')}</ul>`);
});
// type('text') gửi văn bản thuần túy, nên mỗi tiêu đề hiển thị trên một dòng riêng.
app.get('/recipes', (req, res) => {
const { tag } = req.query;
const list = tag ? recipes.filter((recipe) => recipe.tags.includes(tag)) : recipes;
res.type('text').send(list.map((recipe) => recipe.title).join('\n'));
});
app.get('/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).send('No such recipe');
return;
}
res.send(recipe.title);
});
app.get('/api/recipes', (req, res) => {
res.json(recipes);
});
app.get('/api/recipes/:id', (req, res) => {
const recipe = recipes.find((r) => r.id === Number(req.params.id));
if (!recipe) {
res.status(404).json({ error: 'No such recipe' });
return;
}
res.json(recipe);
});
app.get('/about', (req, res) => {
res.send('Recipe Box collects family recipes.');
});
app.get('/menu', (req, res) => {
res.redirect(301, '/recipes');
});
app.get('/menu/:id', (req, res) => {
res.redirect(301, `/recipes/${req.params.id}`);
});
app.listen(3000, () => {
console.log('Recipe Box is running on port 3000');
});
Bài học này có một bài trắc nghiệm ngắn. Bắt đầu bài học để trả lời và theo dõi tiến độ.
Tất cả bài học trong Kiến thức cơ bản về Express
1Máy chủ đầu tiên của bạn
Xin chào, ExpressModule httpThêm tuyến đườngTham số tuyến đường3Middleware
Middleware đầu tiên của bạnTự luyện tập: Playground Express