Definition

Hàm dùng làm tham số của hàm khác thì gọi là callback.

Xét ví dụ sau:

// Callback function
function square(n) {
  return n ** 2
}
 
function cube(square, n) {
  return square(n) * n
}
 
console.log(cube(square, 3)) // 27

Ví dụ khác:

const numbers = [1, 2, 3, 4, 5]
 
function sumArray(arr) {
  let sum = 0
 
  // Callback function
  function cummulate(element) {
    sum += element
  }
 
  arr.forEach(cummulate)
 
  return sum
}
 
console.log(sumArray(numbers)) // 15

Phương thức forEach gọi thực hiện hàm cummulate cho mỗi phần tử có trong mảng.

Đoạn code trên có thể viết gọn lại như sau:

const numbers = [1, 2, 3, 4, 5]
 
function sumArray(arr) {
  let sum = 0
 
  // Anonymous callback
  arr.forEach(function (element) {
    sum += element
  })
 
  return sum
}
 
console.log(sumArray(numbers)) // 15

Note

Bản thân callback không tạo ra sự bất đồng bộ hay trì hoãn việc trả về giá trị. Mấu chốt nằm ở chỗ đa số các hàm nhận vào callback lại là các hàm bất đồng bộ.

Higher Order Function and Returning Function

Hàm mà nhận tham số là một callback hoặc trả về một hàm khác thì được gọi là higher order function.

function higherOrder(n) {
  function doSomething(m) {
    function doWhatEver(t) {
      return 2 * n + 3 * m + t
    }
    return doWhatEver
  }
  return doSomething
}

Hàm được trả về được gọi là returning function.

Callback Hell

Khi xử dụng callback, có thể xảy ra một vấn đề liên quan đến clean code. Vấn đề này có tên là callback hell, xảy ra khi có quá nhiều callback lồng vào nhau.

Giả sử ta cần lấy liên tiếp ba hình ảnh từ API, điều này sẽ gây ra callback hell như sau:

function getImages(url, tasks) {
  const data = "Data"
  tasks(data)
}
 
getImages("URL1", function (data1) {
  console.log(data1)
  getImages("URL2", function (data2) {
    console.log(data1, data2)
    getImages("URL3", function (data3) {
      console.log(data1, data2, data3)
    })
  })
})

Hoặc một ví dụ đau đớn hơn:

Callback hell làm cho code khó đọc và khó kiểm soát lỗi.

Seealso