Bạn có biết Callback là gì không? Đối với những người mới học lập trình, khái niệm này thường gây khó khăn và nhầm lẫn. Trong bài viết này, mình sẽ giới thiệu về callback trong JavaScript, bởi vì nó rất đơn giản và dễ hiểu. Mình sẽ cố gắng viết một cách đơn giản nhất để giúp bạn nắm vững khái niệm này.
Callback là gì?
Đơn giản thì callback là một hàm sẽ được thực thi sau khi một hàm khác đã hoàn thành việc thực thi. Đó là lý do tại sao nó được gọi là “callback” (gọi lại).
Nếu muốn phức tạp hơn một chút, trong JavaScript, các hàm cũng là đối tượng, cho phép chúng ta truyền một hàm làm tham số và trả về một hàm khác. Do đó, bất kỳ hàm nào được truyền vào và được gọi sau đó sẽ được gọi là “callback function”.
Hãy xem một số ví dụ để hiểu rõ hơn về khái niệm này.
Tại sao chúng ta cần callback?
Lý do rất quan trọng chính là JavaScript là một ngôn ngữ xử lý các sự kiện. Thay vì chờ phản hồi, JavaScript vẫn tiếp tục thực thi các lệnh tiếp theo và đợi phản hồi từ các sự kiện khác. Hãy xem một ví dụ sau để hiểu rõ hơn:
function first() {
console.log(1);
}
function second() {
console.log(2);
}
first();
second();
Đúng như bạn mong đợi, hàm đầu tiên sẽ được thực thi trước và hàm thứ hai được thực thi sau. Màn hình console của trình duyệt sẽ hiển thị kết quả như sau:
1
2
Mọi thứ vẫn tốt cho đến khi bạn đặt ra câu hỏi: “Nhưng tại sao nếu hàm đầu tiên chứa mã không thể thực thi ngay lập tức khi được gọi, ví dụ như hàm đó phải gọi API và mất một khoảng thời gian để nhận kết quả?” Để mô phỏng hành động này, ta sử dụng hàm setTimeout
và delay trong 500 mili giây. Đoạn code mới trông như sau:
function first() {
setTimeout(function(){
console.log(1);
}, 500);
}
function second() {
console.log(2);
}
first();
second();
Quan trọng nhất là bạn không cần quan tâm đến cách setTimeout()
hoạt động. Nhưng bạn cần lưu ý rằng chúng ta đã thêm một đoạn mã console.log(1)
với độ trễ 500 mili giây. Vậy điều gì sẽ xảy ra khi chúng ta gọi hai hàm này?
first();
second();
Kết quả sẽ là:
2
1
Như bạn thấy, mặc dù chúng ta gọi hàm đầu tiên trước, nhưng nó lại trả về kết quả sau hàm thứ hai.
Không phải JavaScript không thực hiện theo thứ tự chúng ta mong muốn, vấn đề là JavaScript không đợi hàm đầu tiên thực thi xong mà tiếp tục thực hiện hàm thứ hai. Để đảm bảo rằng JavaScript thực hiện theo thứ tự mà ta mong đợi, ta cần sử dụng callback function. Callback function là cách để đảm bảo rằng code sẽ không hoạt động trước khi các code khác hoàn thành thực thi.
Tạo một callback
Đầu tiên, hãy mở Chrome Developer Console trên trình duyệt của bạn (Windows: Ctrl + Shift + J)(Mac: Cmd + Option + J) và nhập đoạn code sau vào console.log của bạn:
function doHomework(subject) {
alert(`Bắt đầu làm bài tập ${subject}.`);
}
Ở trên, chúng ta đã tạo một hàm doHomework()
. Hàm này nhận một biến là đối tượng mà ta làm việc trên đó. Hãy gọi hàm của bạn bằng cách nhập thông tin sau vào console.log:
doHomework('toán'); // Sẽ hiện thông báo: "Bắt đầu làm bài tập toán."
Giờ chúng ta hãy thêm callback vào như một tham số của hàm. Callback sau đó được định nghĩa là đối số thứ hai bên trong lệnh gọi hàm doHomework()
.
function doHomework(subject, callback) {
alert(`Bắt đầu làm bài tập ${subject}.`);
callback();
}
doHomework('toán', function() {
alert('Hoàn thành bài tập.');
});
Như bạn thấy, nếu bạn nhập code trên vào console.log, bạn sẽ nhận được hai thông báo: “Bắt đầu làm bài tập toán” và “Hoàn thành bài tập”.
Tuy nhiên, callback function không phải lúc nào cũng phải được xác định bên trong lệnh gọi hàm. Chúng có thể được định nghĩa ở nơi khác trong code như sau:
function doHomework(subject, callback) {
alert(`Bắt đầu làm bài tập ${subject}.`);
callback();
}
function alertFinished() {
alert('Hoàn thành bài tập.');
}
doHomework('toán', alertFinished);
Kết quả vẫn giống như trước, nhưng về cách thiết lập có một chút khác biệt. Như bạn thấy, chúng ta đã chuyển định nghĩa hàm alertFinished
làm đối số bên trong lệnh gọi hàm doHomework()
.
Nhiều callback functions
Bạn có thể tạo ra một hàm có nhiều callback function bằng cách tạo ra nhiều tham số, mỗi tham số là một callback function. Dưới đây là một ví dụ khi xử lý ajax bằng jQuery:
function successCallback() {
// Làm gì đó
}
function successCallback() {
// Làm gì đó
}
function completeCallback() {
// Làm gì đó
}
function errorCallback() {
// Làm gì đó
}
$.ajax({
url: "google.com",
success: successCallback,
complete: completeCallback,
error: errorCallback
});
Một vài lưu ý
- Callback phải là một hàm: Callback phải là một function, nếu bạn truyền một kiểu dữ liệu khác, bạn sẽ nhận được thông báo lỗi “Callback is not a function” trên console.
- Từ khóa
this
trong callback: Callback là một hàm bình thường, khi sử dụng từ khóathis
trong hàm, nó sẽ hiểu là đối tượngWindow
. Vì vậy, trong hàm callback, bạn không thể truy cập đến dữ liệu của object thông qua từ khóathis
.
Kết bài
Trên đây là những kiến thức cơ bản về callback mà những người làm việc với JavaScript thường gặp phải. Mong rằng bài viết đã giúp bạn hiểu rõ hơn về callback là gì và cách nó hoạt động. Tuy nhiên, đây chỉ là phần rất nhỏ của callback. Còn rất nhiều điều để bạn khám phá và tìm hiểu. Chúc bạn thành công và may mắn!