Xin chào mọi người, hôm nay mình sẽ giới thiệu về Callback, Promise, Async/Await trong JS, mong mọi người theo dõi
Trước khi tìm hiểu về Callback, Promise, Async/Await trong Javascript thì chúng ta sẽ đi qua một ví dụ sau: Giả sử bạn cần xin số điện thoại của một người mình tạm gọi là bạn ABC từ người bạn của mình là bạn XYZ
Ví dụ
const xinSdt = () => { let sdt; console.log('1 - Gọi điện cho thằnng bạn XYZ, cho tao xin số của thằng ABC'); console.log('2 - XYZ đang tìm số của ABC cho bạn'); // Giả sử thời gian tìm số điện thoại của ABC mất khoảng 1s setTimeout(() => { sdt = 123456789; console.log('3 - XYZ đã tìm thấy số của ABC'); }, 1000); console.log(`4 - Số điện thoại của ABC là ${sdt}`); }; // Gọi hàm để xem kết quả xinSdt();
Kết quả:
Như mọi người thấy thì trước thì thứ tự log ra nó đang là 1243 chứ không phải 1234, vì sao lại như vậy, là vì Javascript là một ngôn như đơn luồng và bất đồng bộ, như ở trong ví dụ trên thì trong code mình có setTimeout cho một đoạn code thì khi hàm xinSdt được thực thi thì nó sẽ không đợi phần mình setTimeout được chạy xong rồi nó mới chạy tiếp mà nó sẽ chạy xuống dưới luôn dẫn tới việc kết quả hiển thị ra là 1243, trong thực tế khi làm việc với JS thì sẽ rất nhiều lúc xẩy ra trường hợp này, ví dụ như khi bạn gọi một API nào đó thì do trong quá trình gọi sẽ mất một khoảng thời gian nào đó để server trả kết quả về thì lúc đó cũng xẩy ra trong hợp tương tự như trên Để giải quyết được vấn đề này trên cho kết quả hiển thị về 1234 thì ta có thể dùng Callback, Promise, Async/Await
Callback function có thể được hiểu như sau: khi ta truyền một đoạn code (Hàm A) này vào một đoạn code khác (Hàm B). Tới một thời điểm nào đó, Hàm A sẽ được hàm B gọi lại (callback). Lý thuyết là vậy giờ chúng ta cùng đi vào ví dụ nhé
Ví dụ 1 Mình sẽ áp dụng callback vào ví dụ ở trên xem thử nó có như mong muốn của chúng ta không nhé
const xinSdt = (callback) => { let sdt; console.log('1 - Gọi điện cho thằnng bạn XYZ, cho tao xin số của thằng ABC'); console.log('2 - XYZ đang tìm số của ABC cho bạn'); // Giả sử thời gian tìm số điện thoại của ABC mất khoảng 1s setTimeout(() => { sdt = 123456789; console.log('3 - XYZ đã tìm thấy số của ABC'); callback(sdt); }, 1000); }; const hienThiSdtSauKhiNhan = sdt => console.log(`4 - Số điện thoại của ABC là ${sdt}`); // Gọi hàm để xem kết quả xinSdt(hienThiSdtSauKhiNhan);
Kết quả:
Giờ thì nó đã hiển thị ra đúng như ta mong muốn là 1234
Trong đoạn code trên thì mình có tách phần hiển thị số điện thoại khi nhận được ra một hàm riêng sau đó mình truyền nó là một tham số của hàm xinSdt thì sau khi mà XYZ tìm được số điện thoại xong thì mới gọi đến hàm hienThiSdtSauKhiNhan thì mình sẽ không bị hiển thị sai kết quả nữa
Nếu mà Callback có thể xử lý được bất đồng bộ rồi thì người ta còn sinh ra Promise với Async/Await làm gì nữa, thì chúng ta sẽ đi vào ví dụ sau:
Ví dụ 2
Giả sử khi XYZ tìm được số điện thoại rồi nhưng mà điện thoại lại hết pin không thể báo lại được cho bạn nữa mà cần phải sạc pin xong mới gọi báo lại được cho mình
const xinSdt = (sacPin) => { let sdt; console.log('Gọi điện cho thằnng bạn XYZ, cho tao xin số của thằng ABC') ; console.log('XYZ đang tìm số của ABC cho bạn'); // Giả sử thời gian tìm số điện thoại của ABC mất khoảng 1s setTimeout(() => { sdt = 123456789; console.log('XYZ đã tìm thấy số của ABC') sacPin(sdt, hienThiSdtSauKhiNhan); }, 1000); } const sacPin = (sdt, hienThiSdtSauKhiNhan) => { console.log('Đang sạc Pin'); setTimeout(() => { console.log('Pin đầy, XYZ bắt đầu gọi điện thoại cho bạn để báo số điện thoại'); hienThiSdtSauKhiNhan(sdt); }, 2000); } const hienThiSdtSauKhiNhan = (sdt) => { console.log(`Đã nhận được số điện thoại của ABC là ${sdt}`); } xinSdt(sacPin);
Kết quả:
Trong ví dụ trên thì khi mà XYZ daxdd tìm được số điện thoại của ABC rồi định gọi điện cho bạn nhưng phát sinh hành động là điện thoại hết pin không thể gọi cho bạn, mà cần phải sạc pin xong mới gọi được cho bạn, giả sử trong quá trình gọi cho bạn mà lại phát sinh thêm các vấn đề khác thì lúc này code sẽ sẽ khá là rối và khó kiểm soát được trong trường hợp này người ta gọi là callback hell. Để code được nhìn dễ dàng hơn thì người ta đã snh ra Promise, vậy chúng ta cùng qua Promise xem xử lý thế nào nhé
Cú pháp
const promise = new Promise(function(resolve, reject) { // Code here });
Trong đó:
Giờ chúng ta sẽ sử dụng Promise để xử lý bài toán ở trên xem thế nào nhé
Ví dụ
const xinSdt = () => { console.log('Gọi điện cho thằnng bạn XYZ, cho tao xin số của thằng ABC'); console.log('XYZ đang tìm số của ABC cho bạn'); // Giả sử thời gian tìm số điện thoại của ABC mất khoảng 1s // phần tìm kiếm này mình sẽ sử dụng Promise const thaoTacTimKiem = new Promise((resolve, reject) => { // Giả sử là tìm thấy số điện thoại của ABC let daTimThaySdt = true; setTimeout(() => { if (daTimThaySdt) { sdt = 123456789; console.log(`XYZ đã tìm thấy số của ABC`); resolve(sdt); } else { reject('XYZ đã tìm và không có số điện thoại của ABC') } }, 1000); }); return thaoTacTimKiem; } // Sac Pin const sacPin = (sdt) => { console.log('Đang sạc Pin'); // Giả sử sạc pin không bị hỏng let sacPinBiHong = false; // Phần sạc pin này mình sẽ sử dụng Promise const thaoTacSacPin = new Promise((resolve, reject) => { setTimeout(() => { if (!sacPinBiHong) { // Pin đã được sạc đầy console.log('Pin đầy, XYZ bắt đầu gọi điện thoại cho bạn để báo số điện thoại'); resolve(sdt); } else { // Sạc pin bị hỏng reject('Sạc Pin bị hỏng rồi'); } }, 2000); }); return thaoTacSacPin; } const hienThiSdtSauKhiNhan = (sdt) => console.log(`Đã nhận được số điện thoại của ABC là ${sdt}`); // Gọi hàm để xem kết quả xinSdt() .then(sdt => { return sacPin(sdt); }) .then((sdt) => hienThiSdtSauKhiNhan(sdt)) .catch(error => { console.log(error); });
Kết quả:
Khi áp dụng Promise vào thì ta thấy code sẽ dễ theo dõi và xử lý hơn
Giờ chúng ta sẽ sử dụng Async/await để xử lý bài toán trên xem thế nào nhé
Ví dụ
const xinSdt = () => { console.log('Gọi điện cho thằnng bạn XYZ, cho tao xin số của thằng ABC'); console.log('XYZ đang tìm số của ABC cho bạn'); // Giả sử thời gian tìm số điện thoại của ABC mất khoảng 1s // phần tìm kiếm này mình sẽ sử dụng Promise const thaoTacTimKiem = new Promise((resolve, reject) => { // Giả sử là tìm thấy số điện thoại của ABC let daTimThaySdt = true; setTimeout(() => { if (daTimThaySdt) { sdt = 123456789; console.log(`XYZ đã tìm thấy số của ABC`); resolve(sdt); } else { reject('XYZ đã tìm và không có số điện thoại của ABC') } }, 1000); }); return thaoTacTimKiem; } // Sac Pin const sacPin = () => { console.log('Đang sạc Pin'); // Giả sử sạc pin không bị hỏng let sacPinBiHong = false; // Phần sạc pin này mình sẽ sử dụng Promise const thaoTacSacPin = new Promise((resolve, reject) => { setTimeout(() => { if (!sacPinBiHong) { // Pin đã được sạc đầy console.log('Pin đầy, XYZ bắt đầu gọi điện thoại cho bạn để báo số điện thoại'); resolve(sdt); } else { // Sạc pin bị hỏng reject('Sạc Pin bị hỏng rồi'); } }, 2000); }); return thaoTacSacPin; } const hienThiSdtSauKhiNhan = (sdt) => console.log(`Đã nhận được số điện thoại của ABC là ${sdt}`); // Gọi hàm để hiển thị kết quả const hanhDong = async () => { try { const sdt = await xinSdt(); await sacPin(sdt); hienThiSdtSauKhiNhan(sdt); } catch (error) { console.log(error); } } hanhDong();
Kết quả:
Nhìn vào logic ở trên ta thấy nó rõ ràng và mạch lạc hơn một chút so với Promise
Lời kết
Trên đây là một số kiến thức cơ bản về xử lý bất đồng bộ trong JavaScript với callback, promise và async/await chứ chưa đầy đủ về Promise hay async/await mà chỉ giúp bạn thấy được cách sử dụng cơ bản, cũng như ưu điểm của chúng so với việc sử dụng callback thông thường. các bạn có thể tiềm hiểu chi tiết hơn ở phía dưới. Cám ơn các bạn đã theo dõi
Nguồn tham khảo
You need to login in order to like this post: click here
YOU MIGHT ALSO LIKE