Chúng ta sẽ viết ứng dụng tính số Fibonacci với Express.
Dãy số Fibonacci là một dãy số có dạng như sau: 0 1 1 2 3 5 8 13 21 34…
Trong đó 2 số đầu tiên luôn luôn là 0 và 1, các số thứ 2 trở đi sẽ có giá trị bằng tổng của 2 số đứng trước nó. Dãy số này được phát minh vào năm 1202 bởi Lenonardo of Pisa.
Đầu tiên chúng ta tạo một project với tên fibonacci (hoặc tên bất kỳ tùy bạn đặt) và thực hiện cài đặt các module như bình thường:
C:\Users\PhoCode>express --ejs fibonacci ... C:\Users\PhoCode>cd fibonacci C:\Users\PhoCode>npm install ...
Đầu tiên chúng ta sửa file app.js
ở thư mục gốc của project như sau:
var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); var routes = require('./routes/index'); var users = require('./routes/users'); var fibonacci = require('./routes/fibonacci'); var app = express(); // view engine setup app.set('views', path.join(__dirname, 'views')); app.set('view engine', 'ejs'); // uncomment after placing your favicon in /public //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico'))); app.use(logger('dev')); app.use(bodyParser.json()); app.use(bodyParser.urlencoded({ extended: false })); app.use(cookieParser()); app.use(express.static(path.join(__dirname, 'public'))); app.use('/', routes); app.use('/users', users); app.use('/fibonacci', fibonacci.index); // catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); }); // error handlers // development error handler // will print stacktrace if (app.get('env') === 'development') { app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: err }); }); } // production error handler // no stacktraces leaked to user app.use(function(err, req, res, next) { res.status(err.status || 500); res.render('error', { message: err.message, error: {} }); }); module.exports = app;
Trong đoạn code trên chúng ta chèn thêm 2 dòng là:
var fibonacci = require('./routes/fibonacci'); ... app.use('/fibonacci', fibonacci.index);
Lưu ý là dòng require()
nên được đặt cùng với các dòng require()
khác cho dễ quản lý, còn dòng app.use()
là phần routing, bạn có thể đặt ở đâu cũng được nhưng phải đặt trước đoạn code dùng để báo lỗi 404 này:
// catch 404 and forward to error handler app.use(function(req, res, next) { var err = new Error('Not Found'); err.status = 404; next(err); });
Lý do là vì Express so sánh các đường dẫn từ trên xuống dưới, nếu không thấy đường dẫn nào khớp thì sẽ trả về trang 404.
Tiếp theo cũng trong thư mục chứa file app.js,
chúng ta tạo một file có tên math.js
với nội dung như sau:
var fibonacci = exports.fibonacci = function(n) { var fibos = []; fibos[0] = 0; fibos[1] = 1; fibos[2] = 1; for(var i = 3 ; i <= n ; i++) fibos[i] = fibos[i - 2] + fibos[i - 1]; return fibos[n]; }
Đây chỉ là module math
chứa hàm tính số Fibonacci viết bằng vòng lặp rất đơn giản.
Tiếp theo chúng ta sẽ tạo các file có đuôi là .ejs,
đây chỉ là các file chứa code HTML để in nội dung lên trang web.
Đầu tiên chúng ta tạo một file có tên top.ejs
trong thư mục views
với nội dung như sau:
<html> <head> <title><%= title %></title> <link rel='stylesheet' href='/stylesheets/style.css' /> </head> <body> <h1><%= title %></h1> <div class='navbar'> <p> <a href='/'>Home</a> | <a href='/fibonacci'>Fibonacci calculator</a> </p> </div>
Cũng trong thư mục views
chúng ta tạo file bottom.ejs
với nội dung như sau:
</body> </html>
Tiếp theo chúng ta chỉnh lại file views/index.ejs
như sau:
<% include top %> <p>Welcome to the Math calculator</p> <% include bottom %>
File index.ejs
được dùng để trả về cho đường dẫn '/'
, các dòng <% include top %>
và <%
include bottom %>
có tác dụng chép đoạn code trong file top.ejs
và bottom.ejs
vào vị trí tương ứng trong file index.ejs.
Đây chỉ là một thủ thuật để chúng ta phân chia các thành phần của một trang web thành các file riêng biệt, sau này khi tạo các trang khác chúng ta cũng chỉ cần thêm các câu lệnh include như thế là được, thay vì phải code lại từ đâu. Các đoạn code nằm trong cặp <%= %>
hoặc <% %>
là code của riêng Express, được dùng để kết nối với code JavaScript chứ không hoàn toàn là code HTML.
Bây giờ chúng ta tạo file fibonacci.ejs
trong thư mục views
với nội dung như sau:
<% include top %> <% if (typeof fiboval !== "undefined") { %> <p>Fibonacci's index: <%= fibonum %></p> <p>Value: <%= fiboval %></p> <% } %> <p>Enter Fibonacci's index:<p> <form name='fibonacci' action='/fibonacci' method='get'> <input type='text' name='fibonum' /> <input type='submit' value='Submit' /> </form> <% include bottom %>
Cuối cùng chúng ta tạo một file có tên fibonacci.js
trong thư mục routes
với nội dung như sau:
var math = require('../math'); exports.index = function(req, res) { if(req.query.fibonum) { res.render('fibonacci', { title: "Calculate Fibonacci numbers", fibonum: req.query.fibonum, fiboval: math.fibonacci(req.query.fibonum) }); } else { res.render('fibonacci', { title: "Calculate Fibonacci numbers", fiboval: undefined }); } };
Thế là xong, chúng ta có thể chạy project (bằng lệnh npm start)
để xem kết quả:
Trang localhost:3000 được trả về từ file views/index.ejs.
Khi chúng ta click vào đường link Fibonacci calculator thì sẽ được chuyển đến trang /fibonacci
có file trả về là views/fibonacci.ejs.
Ở trang này chúng ta có thể nhập số thứ tự và trang web sẽ trả về giá trị Fibonacci đó, chẳng hạn số fibonacci thứ 20 có giá trị là 4181.
Chúng ta sẽ tìm hiểu những gì diễn ra ở server như sau:
Trong file app.js,
chúng ta có 3 đường dẫn routing, 2 đường dẫn đầu tiên là '/'
và '/users'
do Express tự tạo ra (bạn có thể nhập localhost:3000/users
để thấy câu thông báo respond with a resource, đường dẫn thứ 3 là '/fibonacci'
do chúng ta tạo ra. Các hàm res.render()
(trong file index.js
và fibonacci.js)
sẽ dựng trang web với các file .ejs tương ứng.
Có nghĩa là khi chúng ta truy cập localhost:3000/,
Express sẽ chạy đoạn code trong file routes/index.js:
var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router;
Dòng res.render('index', { title: 'Express' });
có chức năng trả về nội dung HTML trong file views/index.ejs
cho người dùng, ngoài ra hàm res.render()
không chỉ gọi file index.ejs
không mà còn truyền tham số vào đó nữa, ở đây tham số là title
có giá trị là Express.
Các tham số này sẽ được dùng trong các file .ejs,
file index.ejs
lại được dựng từ 2 file là top.ejs
và bottom.ejs,
trong đó chỉ có file top.ejs
là sử dụng giá trị trong tham số title (ở dòng code <%= title %>
).
Tương tự, khi chúng ta click vào đường link để được chuyển đến trang /fibonacci
thì hàm index()
trong file routes/fibonacci.js
sẽ được gọi, bởi vì trong file app.js
chúng ta đã chỉ định đường dẫn /fibonacci
sẽ gọi hàm này bằng dòng app.use('/fibonacci', fibonacci.index),
hàm res.render()
sẽ trả về nội dung HTML trong file fibonacci.ejs
cho người dùng, đi kèm là một số tham số là title, fiboval
và fibonum.
Trong file fibonacci.ejs
chúng ta khai báo một form với một textbox và một nút Submit để nhập số thứ tự để tính toán giá trị Fibonacci, textbox ở đây được đặt tên là fibonum,
khi người dùng click nút Submit thì trình duyệt của người dùng sẽ gửi một yêu cầu HTTP đến server với đường dẫn /fibonacci
kèm theo tham số fibonum,
trong file fibonacci.js
chúng ta kiểm tra xem tham số đó có được truyền lên hay không, nếu có thì chúng ta tính toán và trả về trong tham số fiboval,
nếu không thì trả về giá trị undefined,
cũng trong file fibonacci.ejs
chúng ta kiểm tra xem giá trị fiboval
này có khác undefined
hay không, nếu khác thì tức là có một giá trị đã được tính toán và chúng ta cho in ra kèm theo với form luôn.
Ban đầu bạn có thể thấy nó hơi rối rắm nhưng thật ra cũng không có gì khó, bạn chỉ cần ngồi ngẫm nghĩ một tí là sẽ hiểu rõ cách những file này hoạt động cùng nhau như thế nào thôi 🙂