Trong bài này chúng ta sẽ tìm hiểu Callback Function là gì, đồng thời học thêm cách tạo và sử dụng callback function trong Javascript từ căn bản đến nâng cao.
Trong Javascript thì function được coi là first-class objects, điều này có nghĩa function cũng là một loại Object nên ta có thể sử dụng nó giống như các object bình thường khác. Chúng ta có thể lưu trữ function trong một biến, truyền tham số là một function, return một function (closure function). Tất cả đều rất hay phải không các bạn, tuy nhiên nhưng trong phạm vi bài này chỉ đề cập đến cách truyền tham số là một function, hay còn gọi là callback function.
Callback function có thể được hiểu nôm na là một function A được truyền vào một function B thông qua danh sách các tham số của B. Lúc này tại hàm B sẽ gọi đến hàm A để thực hiện một chức năng nào đó mà A đang nắm giữ. Javascript là một ngôn ngữ lập trình hướng sự kiện và bất đồng bộ nên callback function đóng vai trò rất quan trọng, bạn sẽ truyền một callback function vào các sự kiện và xử lý bất đồng bộ đó.
Sau đây là một ví dụ đơn giản về callback function trong jQuery, trong ví dụ này thì phương thức click đã hỗ trợ bạn truyền một callback function.
Một ví dụ khác về hàm setTimeout, đây cũng là một hàm cho phép bạn truyền một callback function.
Việc sử dụng callback function phải hết sức cẩn thận, bạn 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. Sau đây là một ví dụ về hàm forEach, hàm này sẽ có tác dụng lặp một mảng và có hai tham số callback function. Mỗi vòng lặp sẽ truyền hai tham số vào hàm cakback function, tham số thứ nhất đó là giá trị của phần tử đang lặp, tham số thứ hai đó là vị trí (index) của phần tử đó.

Ok bây giờ chắc hẳn bạn đã biết callback function là gì rồi phải không nào, nếu vậy thì ta qua phần 2 tìm hiểu cách hoạt động của nó nhé.
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ó. Như ở phần callback là gì mình có đưa ra một số ví dụ về truyền tham số cho callback 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 bạn truyền 3 tham số thì bạn 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ì.
Để các bạn dễ hiểu thì mình sẽ tự viết một hàm hỗ trợ callback function, bạn hãy xem kỹ ví dụ này nhé.
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ố.
Khi bạn tự viết một hàm có sử dụng tham số là một callback function thì cần chú ý một số vấn đề như sau.
Điều này rất quan trọng bởi nếu bạn không kiểm tra giá trị mà người dùng truyền vào là một #function thì bạn không thể thực thi được, đây là sự khác biệt giữa một lập trình viên non kinh nghiệm và nhiều kinh nghiệm. Xem ví dụ dưới đây để hiểu về cách kiểm tra.
Thông qua ví dụ này ta thấy để kiểm tra một biến có phải là function hay không thì ta sử dụng hàm typeof, nếu typeof có giá trị là "function" thì đó là một function.
Hàm được xây dựng trong Object là hàm được định nghĩa thông qua key của object và giá trị của key là một hàm. Trong ví dụ này hàm setName được xây dựng bên trong object domainInfo.
Theo đúng nguyên tắc thì hàm callback là một hàm đơn phương nên khi bạn sử dụng từ khóa this trong hàm thì nó sẽ hiểu this lúc này chính là đối tượng Window Object, vì vậy cho dù bạn định nghĩa hàm callback nằm trong một object thì không thể truy cập đến dữ liệu của object thông qua từ khóa this.
Bạn hãy xem đoạn code sử dụng hàm setName là một callback function dưới đây để hiểu rõ hơn.
XEM DEMO
Phần demo này mình đã giải thích trong code rồi nên mình không giải thích gì thêm.
Ở phần trên mình đã đưa ra lưu ý khi sử dụng this trong hàm callback thì this sẽ trỏ tới đối tượng window chứ không phải đối tượng chứa hàm callback, vậy có cách nào khắc phục tình trạng này không? Có đấy, chúng ta sẽ sử dụng phương thức apply của hàm callback. Cú pháp như sau:
Nếu ta sử dụng cú pháp này thì từ khóa this sẽ trỏ tới đối tượng callbackObject chứ không phải là window object. Sau đây là đoạn code khắc phục ở ví dụ phía trên.
XEM DEMO
Ngoài phương thức apply thì bạn cũng có thể sử dụng phương thức call để thay thế.
Bạn có thể tạo ra một hàm có nhiều calback function bằng cách tạo ra nhiều tham số và mỗi tham số là một callback function. Xem ví dụ khi xử lý ajax bằng jQuery dưới đây.
Trong bài mình đã giới thiệu khái niệm callback function là gì rồi nhỉ :) nó cũng tương đối đơn giản và mình tin chắc rằng các bạn đã sử dụng rất nhiều nhưng không biết đó là callback function, nhất là khi sử dụng thư viện jQuery.
Khi nói tới callback function thì ta thường nghĩ ngay tới từ khóa callback hell. Đáng lẽ ra mình trình bày trong bài này luôn, tuy nhiên vì bài hơi dài nên mình sẽ trình bày nó ở một bài khác gần đây. Hẹn gặp lại các bạn ở bài tiếp theo nhé.





