Cách sử dụng Callback Functions trong JavaScript

4 min read

Khi bạn đang xây dựng các ứng dụng động bằng JavaScript hiển thị dữ liệu thời gian thực – như ứng dụng thời tiết hoặc trang tổng quan thể thao trực tiếp – bạn sẽ cần một cách để tự động tìm nạp dữ liệu mới từ nguồn bên ngoài mà không làm gián đoạn trải nghiệm người dùng.

Bạn có thể thực hiện việc này bằng cách sử dụng các callback Functions của JavaScript, hàm này thể hiện khả năng xử lý các hoạt động không đồng bộ của JavaScript. Hãy cùng khám phá callback Functions là gì? cách chúng hoạt động và tại sao chúng lại cần thiết trong JavaScript.

Callback Function là gì?

Callback Function là hàm được truyền dưới dạng đối số cho hàm khác và được thực thi sau khi hoàn thành một số thao tác.
Cơ chế này cho phép JavaScript thực hiện các tác vụ như đọc tệp, thực hiện yêu cầu HTTP hoặc chờ người dùng nhập mà không chặn việc thực thi chương trình. Điều này giúp đảm bảo trải nghiệm người dùng mượt mà.

Tại sao sử dụng Callback Function?

JavaScript chạy trong môi trường đơn luồng, nghĩa là nó chỉ có thể thực thi một lệnh tại một thời điểm. Các hàm gọi lại giúp quản lý các hoạt động không đồng bộ, đảm bảo mã tiếp tục chạy trơn tru mà không cần chờ tác vụ hoàn thành. Cách tiếp cận này rất quan trọng để duy trì một chương trình đáp ứng và hiệu quả.

Cấu trúc cơ bản của Callback Function?

function greet(name, callback) {
   console.log(`Hello, ${name}!`);
callback();
} 
function sayGoodbye() { console.log("Goodbye!"); }
greet("Alice", sayGoodbye);

Trong dòng code này:
– Hàm “greet” là 1 hàm lấy tên và hàm callback “sayGoodbye” làm đối số
– Sau khi greet user xong sẽ gọi lại hàm callback “sayGoodbye”

Cách hoạt động của callback Function

  • Truyền hàm: callback Function bạn muốn chạy sau một số thao tác được truyền dưới dạng đối số cho hàm khác.
  • Thực thi callback Function: Hàm chính thực hiện callback Function vào thời điểm thích hợp. Điều này có thể xảy ra sau một thời gian trì hoãn, khi một nhiệm vụ đã hoàn thành hoặc khi một sự kiện xảy ra.

Dưới đây là ví dụ chi tiết hơn về hoạt động không đồng bộ được mô phỏng bằng setTimeout:

function fetchData(callback) {
setTimeout(() => {
   const data = { id: 1, name: "Alice" };
   callback(data);
}, 2000); // Simulating a delay of 2 seconds
}

fetchData((data) => {
  console.log("Data received:", data);
});

Trong ví dụ này:
– FetchData mô phỏng việc tìm nạp dữ liệu sau độ trễ 2 giây.
– Hàm gọi lại ghi lại dữ liệu sau khi nhận được.

<h2> Cách xử lý lỗi trong callback Function</h2>

Trong các tình huống thực tế, bạn thường cần phải xử lý lỗi. Một mẫu phổ biến là chuyển lỗi làm đối số đầu tiên cho hàm gọi lại:

function readFile(filePath, callback) {
   const fs = require('fs');
   fs.readFile(filePath, 'utf8', (err, data) => {
   if (err) {
      callback(err, null);
   } else {
      callback(null, data);
}
});
}

readFile('example.txt', (err, data) => {
if (err) {
    console.error("Error reading file:", err);
} else {
    console.log("File content:", data);
}
});

– Hàm readFile đọc tệp không đồng bộ.
– Nó gọi lại calllback Function với lỗi (nếu có) hoặc dữ liệu tệp.

Vấn đề “Callback Hell”

Khi các ứng dụng phát triển, việc sử dụng nhiều lệnh gọi lại lồng nhau có thể trở nên phức tạp và khó quản lý, thường được gọi là “Callback Hell”. Đây là một ví dụ về Callback Hell:

function stepOne(callback) {
   setTimeout(() => callback(null, 'Step One Completed'), 1000);
}

function stepTwo(callback) {
   setTimeout(() => callback(null, 'Step Two Completed'), 1000);
}

function stepThree(callback) {
   setTimeout(() => callback(null, 'Step Three Completed'), 1000);
}

stepOne((err, result) => {
    if (err) return console.error(err);
        console.log(result);
        stepTwo((err, result) => {
            if (err) return console.error(err);
                console.log(result);
                stepThree((err, result) => {
            if (err) return console.error(err);
                console.log(result);
           });
      });
});

Mã code này khó đọc và bảo trì. Để giải quyết vấn đề này, JavaScript hiện đại cung cấp cú pháp “Promises” và “async/await”, giúp mã code sạch hơn và dễ xử lý hơn.

Cách sử dụng Promise và Async/Await

Promise thể hiện sự hoàn thành (hoặc thất bại) cuối cùng của một hoạt động không đồng bộ và giá trị kết quả của nó.

function fetchData() {
   return new Promise((resolve, reject) => {
      setTimeout(() => {
          resolve({ id: 1, name: "Alice" });
      }, 2000);
  });
}

fetchData()
.then(data => {
   console.log("Data received:", data);
})
.catch(error => {
   console.error("Error:", error);
});

Cú pháp Async/Await đơn giản hóa việc làm việc với Promise:


async function getData() {
   try {
      const data = await fetchData();
      console.log("Data received:", data);
   } catch (error) {
       console.error("Error:", error);
   }
}

getData();

Cách tiếp cận này làm cho mã không đồng bộ nhìn giống và hoạt động giống như mã đồng bộ, cải thiện khả năng đọc và bảo trì.

Kết luận:

  • Callback Function là hàm cơ bản trong JavaScript để xử lý các hoạt động không đồng bộ.
  • Mặc dù chúng cung cấp một cách mạnh mẽ để quản lý luồng không đồng bộ nhưng chúng có thể trở nên phức tạp và khó bảo trì.
  • Sử dụng Promise và cú pháp async/await có thể đơn giản hóa mã của bạn, giúp mã sạch hơn và dễ quản lý hơn.
    Hiểu những khái niệm này sẽ giúp bạn viết mã JavaScript hiệu quả và dễ bảo trì hơn.

Nguồn dịch: https://www.freecodecamp.org/news/how-to-use-callback-functions-in-javascript

Avatar photo

Clean Code: Nguyên tắc viết hàm trong lập trình…

Trong quá trình phát triển phần mềm, việc viết mã nguồn dễ đọc, dễ hiểu là yếu tố then chốt để đảm bảo code...
Avatar photo Dat Tran Thanh
3 min read

Clean Code: Nguyên tắc comment trong lập trình

Trong lập trình, code không chỉ là một tập hợp các câu lệnh để máy tính thực thi, mà còn là một hình thức...
Avatar photo Dat Tran Thanh
3 min read

Clean Code: Nguyên tắc xử lý lỗi (Error Handling)

Trong quá trình phát triển phần mềm, việc xử lý lỗi không chỉ là một phần quan trọng mà còn ảnh hưởng trực tiếp...
Avatar photo Dat Tran Thanh
4 min read

Leave a Reply

Your email address will not be published. Required fields are marked *