CSDL_Thực hành (2) - DBMS

Bài trước: CSDL_Thực hành (1) - Dữ liệu và CSDL
-----
2. DBMS
2.1 DBMS là gì

Như đã đề cập, khi làm việc với CSDL, chúng ta sẽ làm việc với 3 thành phần là [1] dữ liệu, [2] mô hình tổ chức dữ liệu (cách thức tổ chức dữ liệu) và [3] phần mềm quản lý CSDL.

Có 2 mô hình tổ chức dữ liệu phổ biến là Mô hình quan hệ và Mô hình phi quan hệ (NoSQL).

Phần mềm quản lý CSDL (hay Hệ quản trị cơ sở dữ liệu, DataBase Management System), gọi tắt là DBMS, là một phần mềm chuyên dụng, cho phép người dùng thực hiện các thao tác như tạo lập, quản lý và truy xuất dữ liệu trong CSDL. 

DBMS cung cấp các công cụ hỗ trợ để định nghĩa cấu trúc dữ liệu, nhập liệu, thực hiện truy vấn dữ liệu, đồng thời đảm bảo tính bảo mật cho dữ liệu được lưu trữ.

Một số DBMS phổ biến gồm: MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server, MongoDB (NoSQL).

Xem hình minh họa.

2.2 RDBMS là gì

Như đã biết, chúng ta có 2 mô hình tổ chức dữ liệu phổ biến là Mô hình quan hệ và Mô hình phi quan hệ (NoSQL).

Để làm việc với mỗi mô hình dữ liệu sẽ có các DBMS tương ứng.

RDBMS là viết tắt của Relational Database Management System - Hệ quản trị CSDL quan hệ, là một DBMS, dùng để quản lý CSDL theo Mô hình quan hệ.

Một số RDBMS phổ biến:

- MySQL

- PostgreSQL

- Oracle Database

- Microsoft SQL Server

- IBM DB2

2.3 Tải và cài đặt MS SQL Server

MS SQL Server, hay Microsoft SQL Server (gọi tắt là SQL Server), là một hệ quản trị cơ sở dữ liệu quan hệ (RDBMS) do Microsoft phát triển. Đây là một nền tảng mạnh mẽ, linh hoạt và được sử dụng rộng rãi trong các doanh nghiệp để lưu trữ, quản lý và phân tích dữ liệu.

Một số thông tin thêm

- SQL Server tuân thủ mô hình quan hệ, tổ chức dữ liệu thành các bảng với các hàng và cột, tạo mối quan hệ giữa các bảng thông qua các khóa.

- Sử dụng Transact-SQL (T-SQL), một phần mở rộng của SQL, để truy vấn và thao tác dữ liệu. T-SQL cung cấp nhiều tính năng mạnh mẽ để xử lý dữ liệu phức tạp.

- Có tính năng sao lưu và phục hồi dữ liệu, đảm bảo an toàn dữ liệu và khả năng phục hồi khi xảy ra sự cố.

-  Cung cấp các cơ chế bảo mật mạnh mẽ để bảo vệ dữ liệu khỏi truy cập trái phép.

- Tích hợp các công cụ phân tích dữ liệu như SQL Server Analysis Services (SSAS) và SQL Server Reporting Services (SSRS).

- Tích hợp tốt với các sản phẩm và dịch vụ khác của Microsoft, như Windows Server, .NET Framework và Azure.

- Có khả năng mở rộng cao, đáp ứng được nhu cầu của các ứng dụng lớn và phức tạp.

- Có nhiều phiên bản khác nhau, từ phiên bản miễn phí (Express) đến các phiên bản dành cho doanh nghiệp (Enterprise), đáp ứng nhu cầu của nhiều đối tượng người dùng.

SQL Server được dùng trong một số loại ứng dụng phổ biến sau

- Ứng dụng quản lý doanh nghiệp (ERP)

- Hệ thống quản lý quan hệ khách hàng (CRM)

- Kho dữ liệu (data warehouse)

- Ứng dụng web và di động

Ưu điểm

- Tính ổn định và độ tin cậy cao.

- Tích hợp tốt với hệ sinh thái Microsoft.

- Cộng đồng hỗ trợ lớn.

Nhược điểm

- Chi phí bản quyền có thể cao đối với các phiên bản doanh nghiệp.

- Yêu cầu tài nguyên hệ thống tương đối lớn.

Tải SQL Server

- Để tải SQL Server, bạn vào trang Google, gõ từ khóa SQL Server, vào trang chủ của SQL Server để tải phần mềm. Hoặc vào trực tiếp trang web này  https://www.microsoft.com/en-us/sql-server/sql-server-downloads

- Chọn bản SQL Server phù hợp, để học tập nên chọn bản miễn phí, ví dụ Express.

Cài đặt SQL Server

Ở bước tải SQL Server, thực tế chúng ta mới tải được tập tin SQL2022-SSEI-Expr.exe, (kích thước 4MB). Đây thực chất là một trình cài đặt (installer) cho phiên bản SQL Server 2022 Express Edition.

Chạy tập tin SQL2022-SSEI-Expr.exe để bắt đầu việc cài đặt.

Quá trình cài đặt:

- Trong cửa sổ Select an installation type > chọn Basic

- Trong cửa sổ Microsoft SQL Server License Terms > chọn Accept

- Trong cửa sổ Specify SQL Server install location > chọn ổ đĩa để cài đặt, nếu ổ C:\ của máy bạn không còn nhiều dung lượng thì nên chọn cài vào ổ đĩa khác (D:\ hoặc E:\). Nếu cài trong D:\ hoặc E:\ thì cần chỉ ra thư mục cài đặt cụ thể, vì trình cài đặt không cho cài đặt vào thư mục gốc của ổ đĩa. Phần mềm SQL Server cần dùng tới khoảng 6.5GB đĩa cứng. Bấm Install.

Sau khi cài đặt SQL Server, trinh cài đặt có thể gợi ý bạn cài đặt thêm phần mềm SQL Server Management Studio. Bạn có thể cài đặt luôn, hoặc để cài sau.

2.4 Bài tập

Bài tập 2.1 Tải và cài đặt một RDBMS bất kỳ. Ví dụ MS SQL Server, MySQL, hoặc PostgreSQL.

Câu 2.2 RDBMS là gì? Phát biểu nào sau đây không đúng?

A. RDBMS là viết tắt của Relational Database Management System - Hệ quản trị CSDL quan hệ.

B. RDBMS là một DBMS dùng để quản lý CSDL theo Mô hình quan hệ.

C. MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server và IBM DB2 là các ví dụ về RDBMS.

D. RDBMS chỉ hỗ trợ các loại dữ liệu phi cấu trúc, không hỗ trợ dữ liệu có cấu trúc.

Câu 2.3 SQL Server là gì? Phát biểu nào sau đây không đúng?

A. SQL Server là một hệ quản trị cơ sở dữ liệu quan hệ (RDBMS) do Microsoft phát triển.

B. SQL Server không có các công cụ phân tích dữ liệu, không thể tích hợp các công cụ phân tích dữ liệu.

C. SQL Server tuân thủ mô hình quan hệ, tổ chức dữ liệu thành các bảng với các hàng và cột.

D. SQL Server có nhiều phiên bản khác nhau, từ phiên bản miễn phí (Express) đến các phiên bản dành cho doanh nghiệp (Enterprise).

-----
Cập nhật: 12/3/2025
-----
Bài sau:

CSDL_Thực hành (1) - Dữ liệu và CSDL

1. Dữ liệu và CSDL

1.1 Dữ liệu là gì

Trong ngành Công nghệ Thông tin, dữ liệu được hiểu là:

- Một chuỗi gồm một hoặc nhiều ký hiệu (sequence of one or more symbols), như chữ cái, số, ký hiệu đặc biệt (ví dụ: A, 1, $). Đây là cách dữ liệu được biểu diễn ở mức người dùng hoặc mức trừu tượng cao hơn, trước khi máy tính xử lý. Ví dụ, chuỗi "123" hoặc "Xin chào" là dữ liệu dạng ký hiệu mà con người nhập vào hệ thống. Ở mức cơ bản (mức máy tính xử lý), các ký hiệu này sẽ được mã hóa để máy tính hiểu.

- Ở mức lưu trữ thấp nhất (cấp độ phần cứng), mọi dữ liệu trong máy tính đều được biểu diễn bằng bit (binary digits) – tức là 0 và 1. Đây là ngôn ngữ cơ bản mà máy tính sử dụng để lưu trữ và xử lý. Ví dụ: chuỗi "Xin chào” sẽ được mã hóa thành một dãy bit (ví dụ: 01011000  01101001 trong mã ASCII cho chữ "X" và "i"). Tất cả văn bản, hình ảnh, âm thanh cuối cùng đều quy về nhị phân.

- Cần được thông dịch (diễn dịch, xử lý) để trở thành thông tin. Dữ liệu thô (raw data) chỉ là tập hợp ký hiệu hoặc số liệu, không có ý nghĩa cho đến khi được xử lý hoặc diễn dịch để trở thành thông tin (information) – dữ liệu có ngữ cảnh và ý nghĩa. Ví dụ, số "19" là dữ liệu; khi được diễn dịch là "tuổi của bạn", nó trở thành thông tin. Máy tính hoặc con người cần xử lý dữ liệu để hiểu và sử dụng nó.

- Biểu diễn số lượng, tính chất của các đối tượng hoặc chỉ dẫn hoạt động. Ví dụ, biểu diễn số lượng: "5" là số sản phẩm trong kho; biểu diễn tính chất: "đỏ" là màu của một chiếc xe; chỉ dẫn hoạt động: mã lệnh "1010" yêu cầu CPU thực hiện phép cộng.

- Dữ liệu được lưu trữ trên ổ đĩa (HDD, SSD) hoặc các thiết bị khác như RAM, đám mây

- Được tổ chức theo dạng cấu trúc, bán cấu trúc hoặc không cấu trúc.

Xem hình minh họa (dữ liệu được lưu trong máy tính).

Tháp xử lý thông tin

Tháp xử lý thông tin (DIKW Pyramid, hoặc Information Hierarchy) là một mô hình khái niệm phổ biến trong CNTT và quản lý thông tin. Mô hình này mô tả quá trình chuyển đổi từ dữ liệu (data) lên thông tin (information), tri thức (knowledge), và cuối cùng là minh triết/sự khôn ngoan (wisdom).

Trong cuộc sống hàng ngày, dữ liệu quanh ta rất phong phú và ẩn chứa bên dưới nhiều giá trị mà chúng ta ít nhận ra. Từ số bước chân bạn đi mỗi ngày, các giao dịch ngân hàng, đến bài đăng trên mạng xã hội. Tuy nhiên, nếu không được xử lý, nó chỉ là những con số hoặc ký hiệu vô nghĩa, tiềm ẩn giá trị mà con người thường không nhận ra ngay. Ví dụ, hàng triệu giao dịch mua sắm là dữ liệu, nhưng nếu không phân tích, ta không thấy được xu hướng mua hàng nào đang nổi bật.

Do vậy, chúng ta sẽ làm cho máy tính có khả năng lưu trữ và xử lý dữ liệu (data) nhằm tạo ra thông tin (information) có ích; từ đó rút trích ra các tri thức (knowledge) và hỗ trợ cho quá trình ra quyết định (wisdom – minh triết/sự khôn ngoan).

Xem hình minh họa.

Ý nghĩa mỗi tầng của Tháp xử lý thông tin:

- Dữ liệu (Data): nhiều, thô, chưa có ý nghĩa rõ ràng

- Thông tin (Information): dữ liệu được xử lý để có ý nghĩa

- Tri thức (Knowledge): hiểu biết từ thông tin

- Minh triết (Wisdom): áp dụng tri thức vào quyết định thực tế

Ví dụ minh họa:

- Dữ liệu: "50, 60, 70" (nhịp tim đo được trong 3 ngày)

- Thông tin: "nhịp tim trung bình là 60 lần/phút" (máy tính xử lý)

- Tri thức: "nhịp tim tăng dần qua 3 ngày" (phân tích xu hướng)

- Minh triết: "nên đi khám vì nhịp tim bất thường" (quyết định dựa trên tri thức)

1.2 Cơ sở dữ liệu là gì

Hãy tưởng tượng bạn lưu trữ một khối lượng dữ liệu khổng lồ (như số liệu, danh sách, hình ảnh, âm thanh), một cách lộn xộn trong ổ cứng dưới dạng các tập tin riêng lẻ. Hoặc giả sử bạn lưu trữ danh sách hàng ngàn mặt hàng (chưa bán, đã bán), giá cả từng món hàng, và thông tin khách hàng trong các tệp văn bản. Việc tìm kiếm, thêm, xóa hay sửa từng mục trong hàng ngàn dữ liệu như vậy sẽ khó khăn và mất thời gian đến mức nào?

Đây chính là lúc bạn cần một giải pháp để lưu trữ và sử dụng dữ liệu một cách hiệu quả. Giải pháp chính là dùng cơ sở dữ liệu (CSDL). Nó giúp bạn tổ chức dữ liệu ngăn nắp, tìm kiếm nhanh chóng và khai thác thông tin một cách thuận tiện.

Cơ sở dữ liệu (database) là một tập hợp dữ liệu được tổ chức, lưu trữ và quản lý một cách có hệ thống trên máy tính, để bạn có thể dễ dàng truy cập, thêm, sửa, xóa hoặc tìm kiếm thông tin khi cần. Hãy nghĩ về CSDL như một "kho lưu trữ thông minh".

Ưu điểm khi sử dụng cơ sở dữ liệu:

- Giúp người dùng dễ dàng truy cập, quản lý, khai thác và cập nhật thông tin

- Giảm sự trùng lặp thông tin xuống mức thấp nhất

- Có thể truy xuất thông tin theo nhiều cách

- Cho phép nhiều người cùng sử dụng một lúc

- Tăng tính bảo mật cho dữ liệu

- Tăng tính toàn vẹn dữ liệu

- Khả năng mở rộng dễ dàng

1.3 Làm việc với CSDL

Khi làm việc với CSDL, chúng ta quan tâm tới 3 thành phần sau:

- Dữ liệu

- Cách thức tổ chức dữ liệu

- Phần mềm quản lý CSDL

Dữ liệu

Khi làm việc với CSDL, bạn có thể hiểu đơn giản, dữ liệu là tập hợp các thông tin thô (raw facts) được thu thập, lưu trữ và xử lý trong cơ sở dữ liệu. Đây là thành phần cốt lõi, đại diện cho các giá trị thực tế mà hệ thống cần quản lý. Dữ liệu có thể ở dạng số, văn bản, hình ảnh, âm thanh, hoặc bất kỳ định dạng nào khác tùy thuộc vào mục đích sử dụng.

Dữ liệu có một số đặc điểm

- Nguyên bản: chưa qua xử lý hoặc tổ chức thành thông tin có ý nghĩa.

- Đa dạng: có thể là dữ liệu có cấu trúc (structured), bán cấu trúc (semi-structured), hoặc không cấu trúc (unstructured).

- Nguồn gốc: được thu thập từ người dùng, hệ thống, cảm biến, hoặc các nguồn khác.

Ví dụ về dữ liệu:

- Dữ liệu về khách hàng (tên, địa chỉ, số điện thoại).

- Dữ liệu về sản phẩm (tên sản phẩm, giá cả, số lượng).

- Dữ liệu về kết quả học tập của sinh viên (mã sinh viên, điểm số).

Cách thức tổ chức dữ liệu

Khi đã có dữ liệu rồi, chúng ta cần phải có cách thức để tổ chức dữ liệu, nhằm giúp cho việc việc lưu trữ, quản lý và truy xuất được dễ dàng.

Có hai mô hình tổ chức dữ liệu đang được sử dụng phổ biến, gồm:

- Mô hình quan hệ (relational model): dữ liệu được tổ chức dưới dạng các bảng

- Mô hình phi quan hệ (noSQL): dữ liệu được tổ chức dưới dạng phi cấu trúc, hoặc bán cấu trúc như JSON, XML.

Phần mềm quản lý CSDL

Khi đã có cơ sở dữ liệu (CSDL), bao gồm dữ liệu và mô hình tổ chức dữ liệu, chúng ta cần sử dụng các công cụ (phần mềm) để chuyển CSDL vào hệ thống máy tính.

Phần mềm đảm nhận vai trò này được gọi là Phần mềm quản lý CSDL, hay còn được gọi là Hệ quản trị CSDL (Database Management System - DBMS).

Hệ quản trị CSDL (DBMS) là một phần mềm chuyên dụng, cho phép người dùng thực hiện các thao tác như tạo lập, quản lý và truy xuất dữ liệu trong CSDL. DBMS cung cấp các công cụ hỗ trợ định nghĩa cấu trúc dữ liệu, nhập liệu, thực hiện truy vấn dữ liệu, đồng thời đảm bảo tính bảo mật cho dữ liệu được lưu trữ.

Một số DBMS phổ biến:

- MySQL

- PostgreSQL

- Oracle Database

- Microsoft SQL Server

- MongoDB(NoSQL)

1.4 Bài tập

Câu 1.1 Trong lĩnh vực Công nghệ Thông tin, dữ liệu là gì? Phát biểu nào sau đây không đúng?

A. Dữ liệu thô (raw data) đã có ngữ cảnh và ý nghĩa, không cần phải thông dịch (xử lý) để trở thành thông tin.

B. Dữ liệu là một chuỗi gồm một hoặc nhiều ký hiệu, như chữ cái, số, ký hiệu đặc biệt.

C. Ở mức lưu trữ thấp nhất (cấp độ phần cứng), mọi dữ liệu trong máy tính đều được biểu diễn bằng bit (binary digits) – tức là 0 và 1.

D. Dữ liệu được lưu trữ trên ổ đĩa (HDD, SSD) hoặc các thiết bị khác như RAM, đám mây.

Câu 1.2 Cơ sở dữ liệu (database) là gì? Phát biểu nào sau đây không đúng?

A. Cơ sở dữ liệu là một tập hợp dữ liệu được tổ chức, lưu trữ và quản lý một cách có hệ thống trên máy tính.

B. Cơ sở dữ liệu làm tăng sự trùng lặp thông tin lên mức cao nhất.

C. Cơ sở dữ liệu giúp người dùng dễ dàng truy cập, quản lý, khai thác và cập nhật thông tin.

D. Cơ sở dữ liệu cho phép nhiều người cùng sử dụng một lúc.

Câu 1.3 DBMS là gì? Phát biểu nào sau đây không đúng?

A. DBMS là phần mềm cho phép người dùng tạo, quản lý và truy xuất dữ liệu trong CSDL.

B. DBMS cung cấp các công cụ để định nghĩa cấu trúc dữ liệu, nhập dữ liệu, truy vấn dữ liệu và bảo mật dữ liệu.

C. MySQL, PostgreSQL, Oracle Database, Microsoft SQL Server, MongoDB là các ví dụ về DBMS.

D. DBMS chỉ hỗ trợ các mô hình dữ liệu quan hệ, không hỗ trợ mô hình phi quan hệ.

Câu 1.4 Theo “Tháp xử lý thông tin”, quá trình chuyển đổi dữ liệu được thực hiện theo thứ tự nào?

A. Data > Knowledge > Information > Wisdom

B. Information > Data > Knowledge > Wisdom

C. Data > Information  > Wisdom > Knowledge

D. Data > Information > Knowledge > Wisdom

-----

Cập nhật: 11/3/2025

-----

Bài sau: CSDL_Thực hành (2) - DBMS


Web back-end (10) - Hàm callback

Bài trước: Web back-end (9) - Một số chủ đề JavaScript (2)

-----

10. Hàm callback

10.1 Hàm callback là gì

Trong JavaScript, hàm callback là một hàm được truyền vào một hàm khác như một tham số, và sẽ được thực thi sau khi hàm "cha" hoàn thành một tác vụ nào đó. Nói một cách đơn giản, nó là một cách để đảm bảo một đoạn mã được thực thi sau khi một đoạn mã khác hoàn thành.

Hàm callback cũng là một trong ba kỹ thuật được sử dụng để lập trình bất đồng bộ trong JavaScript.

Callback nghĩa là gọi lại.

Các đặc điểm của hàm callback

- Truyền như tham số: callback là một hàm được truyền vào hàm khác để thực thi sau khi một điều kiện hoặc tác vụ hoàn tất.

- Thực thi bất đồng bộ: thường dùng để xử lý các tác vụ không chặn luồng chính (non-blocking), như truy cập thiết bị (đọc/ghi tập tin), gọi API, hoặc trong các hàm hẹn giờ (timer).

- Tính linh hoạt: có thể là hàm ẩn danh (anonymous function), hàm mũi tên (arrow function), hoặc hàm đã được định nghĩa trước (function expression).

- "Callback Hell": nếu lồng quá nhiều callback, mã nguồn có thể trở nên khó đọc và bảo trì. Callback hell thường được giải quyết bằng Promise hoặc async/await.

Một số tính huống có sử dụng hàm callback

- Xử lý sự kiện (event handling): gắn hàm callback để phản hồi hành động của người dùng (ví dụ: click, hover, submit).

- Tác vụ bất đồng bộ: gọi API, đọc/ghi tập tin, hoặc sử dụng trong các hàm hẹn giờ (ví dụ: setTimeout, setInterval).

- Xử lý mảng: sử dụng trong các phương thức như forEach, map, filter, reduce.

- Hoàn thành tác vụ: đảm bảo một đoạn mã chạy sau khi tác vụ khác hoàn tất (ví dụ: tải dữ liệu từ server rồi hiển thị lên giao diện).

- Tùy chỉnh logic: cho phép người dùng truyền logic riêng vào hàm tổng quát.

Một số ví dụ sử dụng hàm callback

Ví dụ 1. Dùng hàm callback trong xử lý sự kiện.

Khi người dùng nhấp vào một nút “Đăng ký”, một sự kiện "click" được kích hoạt. Bạn có thể sử dụng hàm callback để xử lý sự kiện này và thực hiện một hành động nào đó.

[callback1.html]

<!DOCTYPE html>

<html lang="en">

<head>

</head>

<body>

    <button id="dang-ky">Đăng ký</button>

    <script>

        document.getElementById("dang-ky").addEventListener("click", () => {

            alert("Nút đã được bấm!");

        });

    </script>

</body>

</html>

Mở tập tin callback1.html bằng trình duyệt để xem kết quả.

Ví dụ 2. Sử dụng hàm callback trong các hàm hẹn giờ (ví dụ: setTimeout, setInterval).

Khi hàm setTimeout() chạy, nó sẽ đưa luồng xử lý vào trạng thái chờ với thời gian được xác định ở tham số thứ 2 (ví dụ chờ 5000ms = 5 giây). Sau khi hết thời gian chờ, hàm callback sẽ được gọi và thực thi. 

setTimeout(() => {

    console.log("Đã hết 5 giây! (sau 5 giây)");

}, 5000);

console.log("Đang chờ");

Kết quả chạy:

Đang chờ

Đã hết 5 giây! (sau 5 giây)

 

Ví dụ 3. Sử dụng callback trong các phương thức như forEach, map, filter, reduce.

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

numbers.forEach(num => console.log(num * num));

// Kết quả: 1, 4, 9, 16

Ví dụ 4.  Dùng callback trong gọi API

function getUser(userId, callback) {

    fetch(`https://jsonplaceholder.typicode.com/users/${userId}`)

        .then(response => response.json())

        .then(data => callback(null, data)) // Thành công, gọi callback với dữ liệu

        .catch(error => callback(error, null)); // Lỗi, gọi callback với lỗi

}

 

getUser(1, function(error, user) {

    if (error) {

        console.error("Lỗi:", error);

    } else {

        console.log("Tên người dùng:", user.name);

    }

});

// Kết quả: "Tên người dùng: Leanne Graham"

Ví dụ 5.  Callback tùy chỉnh logic, cho phép người dùng truyền logic riêng vào hàm tổng quát. Hàm callback x => x * x cho phép người dùng tự định nghĩa cách xử lý từng phần tử.

function xuLyMang(arr, callback) {

    for (let i = 0; i < arr.length; i++) {

        arr[i] = callback(arr[i]);

    }

    return arr;

}

 

const numbers = [1, 2, 3];

const binhPhuong = xuLyMang(numbers, x => x * x);

console.log(binhPhuong); // Kết quả: [1, 4, 9]

 

const nhan2 = xuLyMang(numbers, x => x * 2);

console.log(nhan2); // Kết quả: [2, 8, 18]

Ví dụ 6. “Callback hell”, hiện tượng lồng quá nhiều callback dẫn đến mã nguồn khó đọc.

setTimeout(() => { console.log("Bước 1 hoàn tất");

    setTimeout(() => { console.log("Bước 2 hoàn tất");

        setTimeout(() => { console.log("Bước 3 hoàn tất");

        }, 1000);

    },1000);

}, 1000);

Nhược điểm của hàm callback

- Callback Hell: lồng quá nhiều callback dẫn đến mã khó đọc.

- Xử lý lỗi phức tạp: cần kiểm tra lỗi thủ công trong mỗi callback.

- Không trực quan: với các luồng phức tạp, khó theo dõi thứ tự thực thi.

Vì vậy, bạn nên sử dụng Promise và Async/Await thay thế cho kỹ thuật callback.

10.2 Bài tập

Bài tập 10.1 Cài đặt các ví dụ trong bài học.

Câu 10.2 Hàm callback trong JavaScript là gì? Phát biểu nào sau đây không đúng?

A. Hàm callback là một hàm được truyền vào một hàm khác như một tham số.

B. Hàm callback thường được sử dụng để xử lý các tác vụ bất đồng bộ.

C. Hàm callback có thể là hàm ẩn danh, hàm mũi tên hoặc hàm đã được định nghĩa trước.

D. Hàm callback được thực thi ngay lập tức sau khi hàm "cha" bắt đầu thực hiện.

Câu 10.3 Callback hell trong JavaScript là gì? Phát biểu nào sau đây không đúng?

A. Callback hell xảy ra khi có quá nhiều hàm callback lồng nhau, khiến mã nguồn khó đọc và bảo trì.

B. Callback hell thường xuất hiện khi xử lý các tác vụ bất đồng bộ phức tạp.

C. Callback hell là một cách hiệu quả để quản lý các tác vụ bất đồng bộ trong JavaScript.

D. Callback hell có thể được giải quyết bằng Promise hoặc async/await.

-----

Cập nhật: 10/3/2025

Bài sau:

Web back-end (9) - Một số chủ đề JavaScript (2)

Bài trước: Web back-end (8) - Một số chủ đề JavaScript (1)

-----

9. Một số chủ đề JavaScript (2)

Ở phần trước, chúng ta đã tìm hiểu về lập trình đồng bộ trong JavaScript, hàm ẩn danh. Chúng ta sẽ tìm hiểu tiếp một số chủ đề liên quan đến lập trình trong JavaScript.

9.1 Hàm mũi tên (arrow function)

Ở phần trước bạn cũng đã được làm quen với hàm mũi tên, phần này chúng ta sẽ tìm hiểu kỹ hơn.

Hàm mũi tên là một tính năng quan trọng được giới thiệu trong ES6 (ECMAScript 2015). Đây là cách viết hàm ngắn gọn và hiện đại trong JavaScript, thường được dùng trong lập trình bất đồng bộ và các tình huống khác.

Hàm mũi tên là một cách định nghĩa hàm trong JavaScript, thay thế cho cú pháp hàm truyền thống (function declaration/expression). Nó sử dụng ký hiệu => (mũi tên) để kết nối tham số và thân hàm, mang lại sự ngắn gọn và một số đặc tính độc đáo về ngữ nghĩa.

Hàm mũi tên giúp viết mã ngắn hơn, dễ đọc hơn, đặc biệt trong các callback hoặc hàm bất đồng bộ.

Sự khác biệt quan trọng của hàm mũi tên chính là cách xử lý từ khóa this (ngữ cảnh) so với hàm thông thường.

Đặc điểm của hàm mũi tên

- Cú pháp ngắn gọn: do loại bỏ từ khóa function, dấu {} và lệnh return trong một số trường hợp

- Không có this (ngữ cảnh) riêng: this trong hàm mũi tên được kế thừa từ phạm vi bên ngoài (lexical scoping), không bị ràng buộc (bound) như hàm thông thường

- Không có arguments: không tự động tạo biến arguments để truy cập danh sách tham số

- Không thể dùng làm hàm tạo (constructor): không thể gọi với từ khóa new để tạo đối tượng

Cú pháp của hàm mũi tên

Cú pháp chung của hàm mũi tên là sử dụng ký hiệu => (mũi tên) để kết nối tham số và thân hàm.

Có 3 cách để viết hàm mũi tên:

- [1] Không tham số: () => { ... }

- [2] Một tham số: x => { ... } (không cần dấu ngoặc cho một tham số)

- [3] Nhiều tham số: (x, y) => { ... }

Một số ví dụ

[1] Hàm không có tham số

const thongBao = () => {

    console.log("Chưa có thông báo, khi nào có thông báo sẽ thông báo!");

}

 

thongBao();

Tình huống: áp dụng trong hàm setTimeout()

setTimeout(() => {

    console.log("Đã hết 4 giây! (sau 4 giây)");

}, 4000);

console.log("Đang chờ");

[2] Hàm có một tham số: x => { ... }

Không cần dấu ngoặc cho hàm chỉ có một tham số. 

Hàm mũi tên có thể tự động trả về kết quả, mà không cần lệnh return.

const binhPhuong = x => x * x;

console.log(binhPhuong(3)); // 9

Tình huống: áp dụng trong duyệt mảng

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

numbers.forEach(num => console.log(num * num));

// Kết quả: 1, 4, 9, 16

[3] Nhiều có tham số: (x, y) => { ... }

const cong = (x,y) => x + y;

console.log(cong(2,4)); //6

Do thân hàm chỉ có một dòng lệnh, nên không cần dấu {}. Hàm tự động trả về kết quả, mà không cần lệnh return.

Từ khóa this trong hàm mũi tên

Như đã đề cập, hàm mũi tên không tạo this (biến ngữ cảnh) riêng, mà lấy this từ phạm vi bao quanh.

Ví dụ: 

function Person() {

    this.age = 0;

    setInterval(() => {

        this.age++; // 'this' tham chiếu đến đối tượng Person

        console.log(this.age);

    }, 1000);

}

 

const p = new Person(); // Kết quả: 1, 2, 3, ... (tăng mỗi giây)

Nếu dùng hàm thông thường (function() { ... }), this sẽ trỏ đến setInterval thay vì Person, gây lỗi. Hàm mũi tên khắc phục vấn đề này.

Mặc dù hàm mũi tên có nhiều ưu điểm như trên. Tuy nhiên, hàm mũi tên không phải lúc nào cũng phù hợp. Trong một số trường hợp, chẳng hạn như khi bạn cần sử dụng đối tượng arguments hoặc khi bạn cần sử dụng hàm làm hàm tạo, bạn nên sử dụng hàm truyền thống. Hoặc khi cần sự rõ ràng trong mã nguồn, hãy dùng function thông thường.

9.2 Lập trình bất đồng bộ trong JavaScript

Nhắc lại một chút về lập trình đồng bộ.

Trong JavaScript, lập trình đồng bộ (synchronous programming) là kỹ thuật lập trình mà các lệnh (statements) được thực thi tuần tự, theo thứ tự từ trên xuống dưới. Mỗi lệnh phải hoàn thành trước khi lệnh tiếp theo được thực thi. Điều này có nghĩa là nếu một tác vụ mất nhiều thời gian (như đọc tập tin, gọi API, giao tiếp client-server), thì toàn bộ chương trình sẽ bị "chặn" (blocked) cho đến khi tác vụ đó hoàn tất.

Ví dụ, một chương trình lập trình theo kiểu đồng bộ.

// chặn luồng

function chanLuong(){

    console.log("Bắt đầu tác vụ cần nhiều thời gian xử lý");

    let batDau = Date.now();

    while(Date.now() - batDau < 5000){

        // Giả lập chờ 5 giây bằng vòng lặp

    }

    console.log("Tác vụ chạy 5 giây hoàn tất")

}

 

console.log("Trước khi chạy tác vụ");

chanLuong() // chặn luồng 5 giây

console.log("Sau khi chạy tác vụ");

JavaScript là một ngôn ngữ đơn luồng, nghĩa là nó chỉ có thể thực hiện một tác vụ tại một thời điểm. Nếu một tác vụ mất nhiều thời gian để hoàn thành, mà chúng ta lại lập trình theo kiểu đồng bộ, thì nó sẽ chặn luồng chính và làm cho ứng dụng không phản hồi.

Lập trình bất đồng bộ giải quyết vấn đề này bằng cách cho phép chương trình tiếp tục thực hiện các tác vụ khác, trong khi chờ đợi tác vụ tốn thời gian hoàn thành.

Lập trình bất đồng bộ là gì?

Trong JavaScript, lập trình bất đồng bộ (asynchronous programming) là một mô hình lập trình cho phép chương trình thực hiện nhiều tác vụ cùng lúc mà không cần chờ đợi tác vụ trước đó hoàn thành. Điều này đặc biệt hữu ích khi xử lý các tác vụ tốn thời gian như yêu cầu xử lý qua mạng (gọi API, giao tiếp client-server), đọc/ghi tập tin hoặc tương tác với cơ sở dữ liệu.

Các kỹ thuật lập trình bất đồng bộ

[1] Callback

- Đây là cách tiếp cận truyền thống để xử lý bất đồng bộ trong JavaScript.

- Một callback là một hàm được truyền vào một hàm khác và được thực thi khi tác vụ bất đồng bộ hoàn thành.

- Tuy nhiên, sử dụng quá nhiều callback có thể dẫn đến "callback hell", khiến mã nguồn trở nên khó đọc và khó bảo trì.

[2] Promises

- Promises là một đối tượng đại diện cho kết quả cuối cùng của một tác vụ bất đồng bộ.

- Chúng cung cấp một cách viết mã bất đồng bộ rõ ràng và dễ bảo trì hơn so với callback.

- then() được sử dụng khi thực hiện thành công, catch() được sử dụng khi gặp lỗi.

[3] Async/await:

- Async/await là một cú pháp mới hơn để viết mã bất đồng bộ, được giới thiệu trong ES2017.

- Nó cho phép bạn viết mã bất đồng bộ trông giống như mã đồng bộ, giúp mã trở nên dễ đọc và dễ hiểu hơn.

- async được đặt trước function, await được đặt trước các lời gọi hàm bất đồng bộ.

9.3 Bài tập

Bài tập 9.1 Cài đặt các ví dụ trong bài học.

Câu 9.2: Hàm mũi tên (arrow function) là gì? Phát biểu nào sau đây không đúng về hàm mũi tên?

A. Hàm mũi tên có cú pháp ngắn gọn, giúp viết mã dễ đọc hơn.

B. Hàm mũi tên có this (ngữ cảnh) riêng, không kế thừa từ phạm vi bên ngoài.

C. Hàm mũi tên không thể được dùng làm hàm tạo (constructor).

D. Hàm mũi tên không có biến arguments để truy cập danh sách tham số.

Câu 9.3: Lập trình bất đồng bộ là gì? Phát biểu nào sau đây không đúng về lập trình bất đồng bộ?

A. Lập trình bất đồng bộ cho phép chương trình thực hiện nhiều tác vụ cùng lúc mà không cần chờ đợi tác vụ trước đó hoàn thành.

B. Lập trình bất đồng bộ đặc biệt hữu ích khi xử lý các tác vụ tốn thời gian như yêu cầu mạng, đọc/ghi tập tin hoặc tương tác với cơ sở dữ liệu.

C. Callback là một kỹ thuật bất đồng bộ, nó sẽ làm cho code dễ đọc và dễ bảo trì hơn khi code có nhiều callback lồng nhau.

D. Async/await cho phép viết mã bất đồng bộ trông giống như mã đồng bộ, giúp mã trở nên dễ đọc và dễ hiểu hơn.

-----

Cập nhật: 10/3/2025

-----

Bài sau: Web back-end (10) - Hàm callback