Sync và Async trong Javascript
JavaScript là ngôn ngữ lập trình Single-thread (đơn luồng), có nghĩa là tại 1 thời điểm chỉ có thể xử lý 1 lệnh. Giờ thì bạn hãy tưởng tượng client gửi request lấy dữ liệu từ một API. Ở đây có thể xảy trường hợp server có thể mất thời gian để xử lý request (tệ hơn là server không trả về kết quả) nếu ở đây đợi đến khi server trả về kết quả mới chạy tiếp thì nó sẽ khiến trang web không phản hồi. Vậy Javascript mới tạo ra Asynchronous để giúp chúng ta làm việc này (như callbacks, Promises, async/await) giúp luồng chạy của web không bị chặn lại khi đợi request. Sau đây chúng ta cùng tìm hiểu về sync, callback(ES5), promise(ES6) và async/await(ES7) trong javascript. I. Đồng bộ và bất đồng bộ:1. Đồng bộ (synchronous/sync) là xử lý theo từng bước. Chỉ khi nào công việc hiện tại thực hiện xong thì mới thực hiện công việc tiếp theo. Điều này sinh ra một trạng thái được gọi là trạng thái chờ.
2. Bất đồng bộ (asynchronous/async) cho phép xử lý nhiều tác vụ cùng lúc. Nếu tác vụ nào xong trước sẽ cho ra kết quả trước.
Lưu ý:
II. Callback (ES5)1. Khái niệm:
Định nghĩa về callback theo trang
2. Ví dụ và cách hoạt động Ví dụ: Con mèo ăn cơm mất 5s sau đó uống nước Ví dụ trên cho kết quả uống nước xong trước ăn cơm mặc dù hàm ăn cơm được gọi trước. => Để con mèo ăn và uống theo đúng trình tự thì chúng ta cần phải có thông tin khi nào con mèo ăn xong mới cho nó uống nước. 3. Ưu nhược điểm của callback
Ví dụ: callback hell
III. Promise (ES6)1. Định nghĩa
2. Cách sử dụng Cách tạo ra một promise: Hàm
Tại mỗi thời điểm, Promise sẽ có những trại thái khác nhau, bắt đầu với
Ví dụ: trước hôm thi đại học, mẹ ngồi cạnh bạn và nói "Cố đỗ đại học rồi mẹ sẽ mua iphone 12 pro max cho". Khi đó, lời hứa của mẹ bạn sẽ trông như sau: Khi một promise được thực hiện, nếu thành công thì sẽ gọi callback trong hàm then, nếu thất bại thì promise sẽ gọi promise trong hàm catch. 3. Promise chaining Nếu xử lý các câu lệnh bất đồng bộ liên tiếp nhau với callback rất dễ dẫn đến tình trạng callback hell như đã nói ở trên khi mà có quá nhiều hàm callback bị lồng vào nhau làm cho việc đọc hiểu cũng như debug trở nên khó khăn. Promise chaining hay chuỗi promise được sinh tra nhằm khắc phục vấn đề trên. Giá trị trả về của hàm 2 sẽ là một promise khác, do đó có thể dùng promise để gọi liên tiếp các hàm bất đồng bộ. Promise thứ hai sẽ được xử lý khi promise thứ nhất trả về 0 hoặc 4.Ví dụ: Có một đoạn callback như sau: Đoạn callback trên sau khi được viết lại bằng Promise:
Trong ví dụ ở trên ta lần lượt gọi đến ba hàm 5, 6 và 7. Chỉ cần một trong ba hàm này bị lỗi, promise sẽ chuyển qua trạng thái reject và callback trong hàm catch sẽ được gọi đến, lúc này việc bắt lỗi sẽ trở nên dễ dàng hơn.Tuy nhiên tiện là như vậy nhưng toàn bộ các hàm 2 chỉ được tính là một câu lệnh. Điều này sẽ gây khó khăn cho việc debug sau này.4. Promise.all() 9 nhận và là một đối số và thông thường là một mảng các promise. Trạng thái của promise này sẽ là 0 nếu trạng thái của tất cả các promise được truyền vào là 0 ngược lại, promise sẽ mang trạng thái 4.5. Promise.race() Khác với 9, hàm 4 sẽ xử lý promise đầu tiên có kết quả trả về không quan tâm kết quả trả về có lỗi hay không.Ví dụ promise1 được resolve đầu tiên nên giá trị mà promise trả về sẽ là giá trị của promise1 và bằng 1. IV. Async/await (ES7)Async/await là cơ chế giúp bạn thực thi các thao tác bất đồng bộ một cách tuần tự hơn , giúp đoạn code nhìn qua tưởng như đồng bộ nhưng thực ra lại là chạy bất đồng bộ, giúp chúng ta dễ hình dung hơn. 1. Async Để định nghĩa một hàm bất đồng bộ với async, ta cần khai báo từ khóa 5 ngay trước từ khóa định nghĩa hàm.Regular function:
Function expression:
Kết hợp với cú pháp arrow function của ES6 Giá trị trả về của Async Function sẽ luôn là một Promise mặc cho bạn có gọi await hay không, nếu trong code không trả về Promise nào thì sẽ có một promise mới được resolve với giá trị lúc đầu (nếu không có giá trị nào trong return kết quả trả về sẽ là undefine). Promise này sẽ ở trạng thái thành công với kết quả được trả về qua từ khóa return của hàm async, hoặc ở trạng thái thất bại với kết quả được đẩy qua từ khóa throw trong hàm async. 2. Await Về cơ bản thì 6 giúp cho cú pháp trông dễ hiểu hơn, thay thì phải dùng 2 nối tiếp nhau thì chỉ cần đặt 6 trước mỗi hàm mà chúng ta muốn đợi kết quả của thao tác bất đồng bộ. Chỉ dùng được 6 trong hàm nào có 5 đứng phía trước. |