Callback

Trong lập trình máy tính, callback là một đoạn code chạy được (thường là một hàm A) được sử dụng như tham số truyền vào của hàm B nào đó. Hàm A được gọi ngay lập tức hoặc trễ một chút sau khi hàm B được gọi. Các ngôn ngữ lập trình khác nhau hỗ trợ callback theo các cách khác nhau, thường được triển khai dưới dạng chương trình con, hàm nặc danh, chuỗi lệnh hoặc con trỏ hàm.

Thiết kế

Có hai loại callback: đồng bộ (blocking callback) và không đồng bộ (asynchronous callback). Trong khi callback đồng bộ được gọi trước khi hàm trả về (trong ví dụ ngôn ngữ lập trình C bên dưới, hàm callback đồng bộ ở đây là hàm main), callback không đồng bộ có thể được gọi sau khi hàm trả về. Callback không đồng bộ thường được dùng trong các thao tác vào / ra hoặc trong việc xử lý sự kiện (event), và được gọi bằng lệnh ngắt hoặc từ các tiểu trình (thread). Callback đồng bộ thường không được sử dụng cho việc đồng bộ dữ liệu giữ liệu giữa các thread.

Callback được dùng nhiều trong các chương trình có sử dụng giao diện cửa sổ. Trong trường hợp này, chương trình X cung cấp (1 tham chiếu tới) hàm callback Y của nó cho hệ điều hành và để cho hệ điều hành gọi hàm Y này, từ đó  chương trình X có thể bắt và xử lý sự kiện click chuột hoặc ấn phím….(do hệ điều hành tạo ra)  bằng hàm Y. Vấn đề được quan tâm ở đây là quyền hạn thực hiện và tính bảo mật. Vì hàm Y của chương trình X được gọi bởi hệ điều hành, Y không nên có cùng quyền hạn với các hàm khác của hệ thống.

Cài đặt

Cách tạo và gọi callback rất khác nhau giữa các ngôn ngữ lập trình:

  • Assembly, C, C++, Pascal, Modula2 và các ngôn ngữ tương tự, một con trỏ hàm có thể được dùng như là tham số cho 1 hàm khác. Điều này được hỗ trợ bởi phần lớn trình biên dịch và cho phép dùng đồng thời nhiều ngôn ngữ khác nhau mà không cần đến thư viện hoặc lớp. Ví dụ như Windows API có thể được gọi trực tiếp từ nhiều ngôn ngữ lập trình và trình biên dịch khác nhau.
  • Nhiều ngôn ngữ thông dịch, như là Javascript, Lua, Python, Perl và PHP, cho phép sử dụng  đối tượng định nghĩa hàm làm tham số.
  • Trong lập trình hướng đối tượng, với ngôn ngữ mà không cho phép dùng hàm làm tham số của hàm khác như trong Java phiên bản < 8, việc sử dụng callback được tạo ra bằng cách dùng đối tượng của lớp dạng abstract hoặc interface làm tham số. Cách dùng callback này được ứng dụng để cài đặt một số design pattern như: Visitor, Observer và Strategy. 

Ví dụ sử dụng

Javascript

function myFunction() {
    document.getElementById("demo").innerHTML = "Hello World";
}

document.getElementById("myBtn").addEventListener("click", myFunction);
// Hệ điều hành sẽ gọi hàm callback “myFunction” khi sự kiện click chuột trên element có ID là “myBtn” xảy ra

C/C++

Ví dụ 3:

#include <stdio.h>
#include <stdlib.h>

void PrintTwoNumbers(int (*numberSource)(void)) {
    printf("%d and %d\n", numberSource(), numberSource());
}

/* Hàm callback */
int overNineThousand(void) {
    return (rand() % 1000) + 9001;
}

/* Hàm callback. */
int meaningOfLife(void) {
    return 42;
}

int main(void) {
    PrintTwoNumbers(&rand);
// Kết quả có thể là “125185 and 8914334”.
// Hàm rand() được dùng làm tham số, điều này tương đương với
// “printf("%d and %d\n", rand(), rand());” trong hàm PrintTwoNumbers

    PrintTwoNumbers(&overNineThousand);
// Kết quả có thể là “9084 and 9441”.
// Hàm overNineThousand được dùng làm tham số, điều này tương đương với
// “printf("%d and %d\n", overNineThousand (), overNineThousand ());” trong hàm PrintTwoNumbers

    PrintTwoNumbers(&meaningOfLife);
// Kết quả là “42 and 42”.
// Hàm meaningOfLife được dùng làm tham số, điều này tương đương với
// “printf("%d and %d\n", meaningOfLife (), meaningOfLife ());” trong hàm PrintTwoNumbers

    return 0;
}

Ví dụ 4:

/*
 * This is a simple C program to demonstrate the usage of callbacks
 * The callback function is in the same file as the calling code.
 * The callback function can later be put into external library like
 * e.g. a shared object to increase flexibility.
 *
 */

#include <stdio.h>
#include <string.h>

typedef struct _MyMsg {
        int appId;
        char msgbody[32];
} MyMsg;

void myfunc(MyMsg *msg)
{
        if (strlen(msg->msgbody) > 0)
                printf("App Id = %d \nMsg = %s \n",msg->appId, msg->msgbody);
        else
                printf("App Id = %d \nMsg = No Msg\n",msg->appId);
}

/*
 * Prototype declaration
 */
void (*callback)(MyMsg *);

int main(void)
{
        MyMsg msg1;
        msg1.appId = 100;
        strcpy(msg1.msgbody, "This is a test\n");
        
        /*
         * Assign the address of the function "myfunc" to the function
         * pointer "callback" (may be also written as "callback = &myfunc;")
         */
        callback = myfunc;

        /*
         * Call the function (may be also written as "(*callback)(&msg1);")
         */
        callback(&msg1);
        
        return 0;
}
/* Output is: 
App Id = 100
Msg = This is a test
*/

Xem thêm

Tham khảo

  • "Perl Cookbook - 11.4. Taking References to Functions". Truy cập 2008-03-03.
  • "Advanced Perl Programming - 4.2 Using Subroutine References". Truy cập 2008-03-03.
  • "PHP Language Reference - Anonymous functions". Truy cập 2011-06-08.
  • "What's New in JDK 8". oracle.com.
  • "Callbacks". Mozilla Developer Network. Truy cập ngày 13 tháng 12 năm 2012.
  • "Creating Javascript Callbacks in Components". Mozilla Developer Network. Truy cập ngày 13 tháng 12 năm 2012.
  • x
  • t
  • s
Dùng cho kỹ nghệ
Dùng trong giảng dạy
Có giá trị lịch sử
  • ABC
  • ALGOL
  • APL
  • BASIC
  • Clipper
  • COBOL
  • Hope
  • MUMPS
  • Pascal
  • PL/I
  • PowerBuilder
  • Simula
  • x
  • t
  • s
Mô tả kiến trúc · Mô tả phần cứng · Đánh dấu · Lập mô hình · Ngôn ngữ lập trình · Query · Specification · Stylesheet · Template processing · Transformation
  • x
  • t
  • s
Paradigm
Cấp độ
Có liên quan
  • Ngôn ngữ lập trình không dựa trên tiếng Anh
  • Off-side rule
  • Ngôn ngữ lập trình trực quan
  • x
  • t
  • s
Những lĩnh vực chính của khoa học máy tính
Các nền tảng toán học
Lý thuyết phép tính
Độ phức tạp Kolmogorov · Lý thuyết Automat · Lý thuyết tính được · Lý thuyết độ phức tạp tính toán · Lý thuyết điện toán lượng tử
Các cấu trúc dữ liệu
các giải thuật
Phân tích giải thuật · Thiết kế giải thuật · Hình học tính toán · Tối ưu hóa tổ hợp
Các ngôn ngữ lập trình
Các trình biên dịch
Tính song hành,
Song song,
và các hệ thống phân tán
Công nghệ phần mềm
Phân tích yêu cầu · Thiết kế phần mềm · Các phương pháp hình thức · Kiểm thử phần mềm · Quy trình phát triển phần mềm · Các phép đo phần mềm · Đặc tả chương trình · LISP · Mẫu thiết kế · Tối ưu hóa phần mềm
Kiến trúc hệ thống
Kiến trúc máy tính · Tổ chức máy tính · Các hệ điều hành · Các cấu trúc điều khiển · Cấu trúc bộ nhớ lưu trữ · Vi mạch · Thiết kế ASIC · Vi lập trình · Vào/ra dữ liệu · VLSI design · Xử lý tín hiệu số
Viễn thông
Mạng máy tính
Các cơ sở dữ liệu
Các hệ thống thông tin
Hệ quản trị cơ sở dữ liệu · Cơ sở dữ liệu quan hệ · SQL · Các giao dịch · Các chỉ số cơ sở dữ liệu · Khai phá dữ liệu · Biểu diễn và giao diện thông tin · Các hệ thống thông tin · Khôi phục dữ liệu · Lưu trữ thông tin · Lý thuyết thông tin · Mã hóa dữ liệu · Nén dữ liệu · Thu thập thông tin
Trí tuệ nhân tạo
Lập luận tự động · Ngôn ngữ học tính toán · Thị giác máy tính · Tính toán tiến hóa · Các hệ chuyên gia  · Học máy · Xử lý ngôn ngữ tự nhiên · Robot học
Đồ họa máy tính
Trực quan hóa · Hoạt họa máy tính · Xử lý ảnh
Giao diện người-máy tính
Khả năng truy cập máy tính · Giao diện người dùng · Điện toán mang được · Điện toán khắp mọi nơi · Thực tế ảo
Khoa học tính toán
Cuộc sống nhân tạo · Tin sinh học · Khoa học nhận thức · Hóa học tính toán · Khoa học thần kinh tính toán · Vật Lý học tính toán · Các giải thuật số · Toán học kí hiệu
Chú ý: khoa học máy tính còn có thể được chia thành nhiều chủ đề hay nhiều lĩnh vực khác dựa theo Hệ thống xếp loại điện toán ACM.