1. Callbacks trong JavaScript là gì?

Callbacks trong Js có tên đầy đủ là callbacks function . Nó là một hàm được truyền vào hàm khác dưới dạng một đối số. Hàm callback sẽ được gọi từ bên trong một hàm khác, và chúng ta gọi hàm nhận hàm callback dưới dạng đối số là hàm bậc cao hơn(higher-order function).

Nói một cách đơn giản hơn là callbacks là hàm được gọi bởi một hàm khác. Nó sẽ được thực thi sau khi một function khác đã được thực thi xong. Vì vậy nó mới có tên là callbacks – gọi lại.

Ví dụ: ta truyền một đoạn code của hàm A này vào một đoạn code khác của hàm B . Tới một thời điểm nào đó, hàm A sẽ được hàm B gọi lại (callback). Mối quan hệ giữa hai hàm này tương tự như mối quan hệ cha con vậy.

function A(){
   // code
}
 
// Hàm B có một tham số callback
function B(callback){
    callback();
}
 
// Gọi hàm B và truyền tham số là hàm A
B(A);

Trong Js thì hàm cũng là một loại đối tượng, và đó là lý do vì sao chúng ta có thể truyền hàm callback dưới dạng đối số cho một hàm khác.

Lưu ý

Mình muốn lưu ý luôn từ đầu là việc sử dụng callback function phải hết sức cẩn thận. Ta phải tuân thủ đúng nguyên tắc mà hàm đó đưa ra, có hàm sẽ truyền thêm tham số cho hàm callback và có hàm thì không.

2. Nguyên lý hoạt động của Callbacks trong JavaScript

Một hàm hỗ trợ callback function thì chắc chắn trong code xử lý của nó sẽ có gọi đến để thực thi hàm callback đó. Nhưng vấn đề nó gọi tại vị trí nào trong hàm là điều chúng ta không hề biết, trừ khi chúng ta tự viết nó. Khi truyền tham số cho callbacks function , các tham số này sẽ phụ thuộc vào hàm cha (hàm xử lý chính). Nếu hàm cha cho phép truyền 3 tham số thì chỉ được truyền 3 tham số, nếu bạn truyền nhiều hơn thì cũng không có tác dụng gì.

Ví dụ:

// Hàm tạo chuỗi mật khẩu
function createPassword(callback) {
    return callback('laptrinhtudau.com');
}
 
// Sử dụng
var password = createPassword(function (secret_key) {
    return secret_key;
});
 
alert(password);

Nếu bạn để ý kỹ hơn thì callback function là một closure function bởi hàm closure sẽ được định nghĩa bên trong một hàm, mà callback function lại là một hàm và nó được xử lý bên trong một hàm khác (đúng với định nghĩa closure), chỉ có một điều khác đó là hàm closure được truyền vào thông qua tham số.
Chúng ta có thể truyền hàm callback vào tương tự như tham số bình thường. Giống như cách chúng ta vẫn làm với các kiểu dữ liệu khác vậy. Nghĩa là khi truyền một callback vào một hàm khác thì callback tuy nó là một hàm nhưng sẽ không có dấu “()” sau tên hàm. Điều đó giúp cho hàm callback không được thực thi, mà chỉ được truyền vào như một tham số mà thôi.

function doSomething() {
    alert('vào');
}
function something(doCallback) {
    doCallback();
}
something(doSomething);

Trong ví dụ trên doSomething tuy là một hàm. Nhưng khi được truyền vào hàm something() thì sẽ không có dấu “()” nữa. Hàm something() muốn thực thi được doSomething thì chỉ cần thêm dấu “()” sau tên hàm là được.

3. Tác dụng của Callbacks trong JavaScript

Chúng ta cần hàm callback vì một lý do rất quan trọng và cũng đơn giản – Js là ngôn ngữ hướng sự kiện. Ta sẽ truyền callback function vào các hàm xử lý sự kiện và hàm xử lý bất đồng bộ đó.

Điều này có nghĩa là thay vì chờ phản hồi trước khi tiếp tục, Js vẫn sẽ tiếp tục thực thi các lệnh tiếp theo. Đồng thời vẫn chờ đợi phản hồi từ các sự việc khác.

Ví dụ:

function first(){
    document.write("PHP");
}
function second(){
    document.write("Js");
}
first();
second();
  • Trình biên dịch đọc mã từ trên xuống dưới, từ trái qua phải.
  • Hàm viết trước thì được thực hiện trước và hàm viết sau thì được thực hiện sau.

Nếu hàm first chứa một số loại code không thể thực thi ngay lập tức thì sao? Callbacks sẽ lên tiếng. Còn như thế thì ta sẽ học ở phần sau nhé.

Ngoài ra, Callback có khá nhiều ứng dụng như sau:

  • Gọi 1 hàm khi có 1 số sự kiện xảy ra. VD như khi click vào 1 nút ta gọi hàm A, khi tắt cửa sổ ta gọi hàm B, v…v.
  • LINQ được xây dựng dựa trên khái niệm callbacklambda expression . Với callback , ta có thể thực hiện các thao tác như: Tìm 1 phần tử trong mảng, lọc phần tử trong mảng, sắp xếp mảng, … trở nên vô cùng đơn giản và thuận tiện.