Callback
Callback là một hàm được truyền qua đối số trong 1 hàm khác (tạm gọi là hàm cha). Khi hàm cha được gọi, hàm callback sẽ được thực thi sau khi một số hành động cụ thể trong hàm cha hoàn thành.
Callback giúp JavaScript mạnh mẽ hơn trong xử lý bất đồng bộ, tùy chỉnh cách xử lý mà không cần sửa đổi code gốc, tái sử dụng code, xử lý sự kiện,...
Ví dụ về callback
setTimeout(function (){
console.log("hello");
},1000);
Hàm truyền vào cho setTimeout ở tham số thứ nhất là hàm callback.
// Ví dụ 1:
// Hàm này sẽ chạy sau 1 giây do setTimeout là bất đồng bộ
setTimeout(() => {
console.log("Program 1");
}, 1000);
// Hàm program2 nhận một callback và thực thi nó ngay sau khi log "Program 2"
const program2 = (callback) => {
console.log("Program 2");
callback(); // Gọi hàm callback được truyền vào
}
// Gọi program2 và truyền vào một callback (hàm program3)
program2(() => {
console.log("Program 3");
});
// Output:
// Program 2
// Program 3
// Program 1
- Hàm setTimeout được gọi nhưng chưa thực thi ngay.
- Hàm setTimeout sẽ đưa callback (hàm Program 1) vào hàng đợi và chờ 1 giây và thực hiện dòng mã tiếp theo in ra hàm "Program 2".
- Hàm program3 (callback) được truyền vào program2 và thực thi in ra "Program 3".
- Sau 1 giây, callback trong setTimeout mới thực thi in ra "Program 1".
//Ví dụ 2
const kiemTraSoDuong = (number) => {
if(number >= 0) {
console.log("Đây là số dương")
}
else {
console.log("Đây là số âm")
}
}
const tinhTong = (a, b, callback) => {
const ketQua = a + b
callback(ketQua)
}
tinhTong(-5,4, kiemTraSoDuong)
//Ví dụ 3:
const loginSucces = () => {
console.log("Đăng nhập thành công")
}
const checkLogin = (data, callback) => {
const email = "tendangnhap@gmail.com"
const password = "1234"
if (data.email === email && data.password === password) {
callback()
}
else {
console.log("Đăng nhập thất bại")
}
}
let user1 = {
email : "tendangnhap@gmail.com",
password : "1234"
}
checkLogin(user1, loginSucces)
Callback Hell
Callback Hell là một tình huống trong JavaScript khi nhiều hàm callback lồng nhau khiến mã khó đọc và khó bảo trì.
Điều này thường xảy ra khi xử lý các hoạt động bất đồng bộ, như tạo yêu cầu API hoặc xử lý tệp I/O, trong đó một hoạt động phụ thuộc vào kết quả của hoạt động khác hoặc hoạt động trước đó.
Giải pháp là có thể sử dụng Promise hoặc Async/Await để code trở lên dễ đọc hơn.
Promise
Promise có 3 trạng thái:
Pending:
- Khi promise đang chạy thì sẽ ở trạng thái này.
- Kết quả là undefined.
Fulfilled:
- Khi promise đã chạy xong thì sẽ ở trạng thái này.
- Kết quả là một giá trị.
Rejected:
- Khi promise bị lỗi thì sẽ ở trạng thái này.
- Kết quả là một object lỗi.
Cú pháp:
var promise = new Promise((resolve, reject)=> {
//resolve() : Nếu thành công chyạ vào hàm này
//reject() : Nếu thất bại chạy vào hàm này
})
promise
.then((success) => {
//Nếu thành công chạy vào đây
})
.catch((error) => {
//Nếu thành công chạy vào đây
})
.finally(() => {
//Luôn luôn chạy vào đây
})
ví dụ:
var a = 10;
var promise = new Promise((resolve, reject) => {
if(a === undefined) {
reject();
} else {
resolve(a);
}
});
promise
.then((resultA) => {
console.log(resultA);
return resultA;
})
.then((resultA) => {
const resultB = resultA + 10;
console.log(resultB);
return resultB;
})
.then((resultB) => {
const resultC = resultB * 20;
console.log(resultC);
})
.catch(() => {
console.log("Thất bại!");
})
.finally(() => {
console.log("Luôn chạy vào đây!");
})
- Trong ví dụ này, a = 10 nên hàm resolve được gọi, truyền giá trị 10 vào phương thức then() đầu tiên.
- Phương thức then() đầu tiên nhận được giá trị 10 và ghi ra console, sau đó trả lại giá trị 10.
- Phương thức then() thứ hai nhận được giá trị 10 từ then() trước, cộng thêm 10 để thành 20 và ghi ra console, sau đó trả lại giá trị 20.
- Phương thức then() thứ ba nhận được giá trị 20 từ then() trước, nhân với 20 để thành 400 và ghi ra console.
- Cuối cùng, finally() luôn được thực thi bất kể Promise hoàn thành hay bị từ chối, và console "Luôn chạy vào đây!".
Promise khiến code trở nên dễ hiểu hơn, xử lí được callback hell.
Async/Await
Async/Await là một tính năng của JavaScript giúp chúng ta làm việc với các hàm bất đồng bộ theo cách dễ hiểu hơn.
Nó được xây dựng trên Promise.
Async: Khai báo một hàm bất đồng bộ.
- Tự động biến đổi một hàm thông thường thành một Promise.
- Từ khóa Async được đặt trước 1 hàm.
Await: Tạm dừng việc thực hiện các hàm async.
- Khi được đặt trước một Promise, nó sẽ đợi cho đến khi Promise kết thúc và trả về kết quả.
- Await chỉ có thể được sử dụng bên trong các hàm async. Ví dụ:
var a = 10;
const getResult = async () => {
try {
if (a === undefined) {
throw new Error("Thất bại!");
} else {
const resultA = a;
console.log(resultA);
const resultB = resultA + 10;
console.log(resultB);
const resultC = resultB * 20;
console.log(resultC);
}
} catch (error) {
console.log(error.message);
}
};
getResult();
Top comments (0)