Javascript là ngôn ngữ lập trình hàng đầu cho cả front end và back end với tính linh hoạt và dễ học. Tuy nhiên, việc viết mã để vừa chạy tốt mà còn dễ bảo trì và mở rộng là một thách thức đối với lập trình viên. Trong bài viết này, chúng ta sẽ khám phá cách sử dụng Promise để tối ưu hóa code bất đồng bộ trong Javascript, giúp code trở nên sạch sẽ và dễ đọc hơn.
Tại sao Promise là một lựa chọn tuyệt vời?
Promise cung cấp một cách tiếp cận mạch lạc và hiệu quả để xử lý các tác vụ bất đồng bộ trong Javascript. Điều này giúp giảm thiểu vấn đề “callback hell”, một hiện tượng phổ biến khi sử dụng các phương thức gọi lại truyền thống.
Xét một trường hợp cụ thể, bạn cần truy xuất dữ liệu từ API (ví dụ: //catfact.ninja/fact) và hiển thị nó trên giao diện. Bằng cách sử dụng Promise thay vì phương thức callback thông thường, mã nguồn của bạn không chỉ gọn gàng hơn mà còn dễ đọc và bảo trì hơn.
{ “fact”: “In Japan, cats are thought to have the power to turn into super spirits when they die. This may be because according to the Buddhist religion, the body of the cat is the temporary resting place of very spiritual people.i”, “length”: 220 } |
Cách sử dụng Promise
Hãy so sánh hai cách tiếp cận: sử dụng callback thông thường và sử dụng Promise. Chúng ta sẽ thấy rõ sự khác biệt về cách viết mã, cũng như cách xử lý các trường hợp thành công và thất bại trong từng phương pháp.
Bình thường, nếu bạn sử dụng Jquery để gọi API sẽ dùng callback như sau:
$.getJSON(‘//catfact.ninja/fact’,function(data) { console.log(data.fact) $(‘body’).append(data.fact); }); |
Đoạn code rất đơn giản, chúng ta sử dụng Jquery để gọi tới API, khi nào API phản hồi và trả về kết quả sẽ được đẩy vào trong callback function(data). Với dự án nhỏ thì đoạn code không vấn đề gì, nhưng nếu phát sinh yêu cầu phải gọi thêm API ngay trong callback. Điều này sẽ dẫn tới vấn đề callback hell.
Để code được được “đẹp” hơn, chúng ta chuyển sang sử dụng promise như sau:
var promise = $.getJSON(‘//catfact.ninja/fact’); promise.done(function(data) { console.log(data.fact) $(‘body’).append(data.fact); }); |
Về cơ bản thì nó tương tự như dùng callback. Trường hợp trên là nếu request thành công, còn nếu thất bại promise sẽ có hàm để xử lý.
var promise = $.getJSON(‘//catfact.ninja/fact’);
promise.done(function(data) { console.log(data.fact) $(‘body’).append(data.fact); }); promise.fail(function() { $(‘body’).append(‘<p>Đã gặp lỗi, đề nghị thử lại!</p>’); }); |
Có thể viết lại như sau:
$.getJSON(‘//catfact.ninja/fact’) .done(function(data) { console.log(data.fact) $(‘body’).append(data.fact); }) .fail(function() { $(‘body’).append(‘<p>Đã gặp lỗi, đề nghị thử lại!</p>’); }); |
Tái sử dụng mã với Promise
Một lợi ích đặc biệt khác của Promise là khả năng tạo ra mã nguồn có tính tái sử dụng cao. Việc tạo các hàm gọi API riêng biệt trả về đối tượng Promise giúp tăng cường tính modular và dễ dàng quản lý.
var catfact = { html : function() { return $.getJSON(‘//catfact.ninja/fact’).then(function(data) { return data.fact; }); } } |
Đối tượng catfact lúc này có một thuộc tính html là một promise object. Điều thú vị là nếu viết như vậy khi cần phải hiển thị ra giao diện chúng ta không quan tâm khi nào thì hàm gọi API xử lý xong mà chỉ quan tâm tới việc hiển thị nó như thế nào.
catfact.html().done(function(html) { $(“body”).append(html); }); |
Hàm then() của promise cho phép chúng ta sửa đổi kết quả của một promise và chuyển nó cho trình xử lý tiếp theo.
Kết hợp nhiều Promise
Khả năng kết hợp nhiều Promise là một trong những tính năng nổi bật nhất. Chúng ta sẽ xem xét cách thức hoạt động của $.when() trong việc xử lý đồng thời nhiều tác vụ bất đồng bộ. Ví dụ:
var firstData = null; var secondData = null; var responseCallback = function() { if (!firstData || !secondData) return; // do something } $.get(“//example.com/first”,function(data) { firstData = data; responseCallback(); }); $.get(“//example.com/second”, function(data) { secondData = data; responseCallback(); }); |
Khi sử dụng hàm when() của Promise để gọi một handler khi cả hai request hoàn thành.
var firstPromise = $.get(“//example.com/first”); var secondPromise = $.get(“//example.com/second”); $.when(firstPromise, secondPromise).done(function(firstData, secondData) { // do something }); |
Promise không chỉ giúp mã nguồn của bạn trở nên dễ đọc và bảo trì hơn mà còn mang lại lợi ích trong việc xây dựng các ứng dụng Javascript mạnh mẽ và linh hoạt. Hy vọng rằng, với những thông tin và mẹo được chia sẻ, các bạn sẽ có thêm công cụ để tối ưu hóa các dự án của mình. Chúc các bạn thành công!
Giảng viên Trần Văn Kỳ
Bộ môn Công nghệ thông tin
Trường Cao đẳng FPT Mạng cá cược bóng đá
cơ sở TP HCM