Javascript là ngôn ngữ đơn luồng (single-threaded), điều này có nghĩa là nó chỉ có thể xử lý một câu lệnh tại một thời điểm. Để loại bỏ rào cản này thì chúng ta có thể sử dụng bất đồng bộ, và bài viết này mình sẽ hướng dẫn và đưa ra những điểm cơ bản của 3 cách viết code bất đồng bộ trong JavaScript.
Bất đồng bộ trong JavaScript là gì?
Bản chất JavaScript là một ngôn ngữ đơn luồng, và nó chỉ chạy trên một luồng (thread) duy nhất. Thread này được dựa trên một khái niệm gọi là event loop. Thread này sẽ phản hồi tới các event khi chúng xảy ra. Là một ngôn ngữ đơn luồng, JavaScript chỉ có thể xử lý từng câu lệnh một. Trong khi đang xử lý câu lệnh đó thì thread sẽ bị block.
Việc đơn luồng này có nhiều ưu điểm, đơn giản nhất là nó sẽ giúp code dễ hơn. Bạn sẽ không cần phải quan tâm đến các vấn đề liên quan đến concurrency. Code của bạn sẽ được thực thi tuần tự từ trên xuống dướii theo cách bạn code. Bạn cũng sẽ không phải lo đến việc có nhiều việc khác nhau chạy trên cùng một thời điểm.
Tuy nhiên nó vẫn có nhược điểm lớn là chỉ có một công việc được làm tại một thời điểm. Mọi việc khác phải chờ đến khi nó hoàn thiện mới có thể được thực thi. Việc này thật sự sẽ là một vấn đề nếu bạn phải lấy data từ một API.
Khi gọi đến API bằng cách đồng bộ/synchronous, việc này có thể block main thread cho đến khi xử lý xong. Do đó code của bạn sẽ phải chờ cho đến khi main thread được mở, đồng nghĩa với việc app của bạn sẽ bị đứng và không có phản hồi.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <span class="token keyword">function</span> <span class="token function">makeAPICall</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Bắt đầu gọi API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Nhận data từ API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Xử lý data'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Đọc data.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// function này sẽ phải chờ đến khi</span> <span class="token comment">// hai function makeAPICall() và processAPIData() chạy xong.</span> <span class="token keyword">function</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Chức năng khác không liên quan đến API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token function">makeAPICall</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Output:</span> <span class="token comment">// 'Bắt đầu gọi API.'</span> <span class="token comment">// 'Nhận data từ API.'</span> <span class="token comment">// 'Xử lý data'</span> <span class="token comment">// 'Đọc data.'</span> <span class="token comment">// 'Chức năng khác không liên quan đến API.'</span> |
Ví dụ ở trên sẽ gặp vấn đề ngay khi có delay ở việc gọi API. Trong trường hợp đó thì code của chúng ta sẽ chạy với một thứ tự khác so với bạn mong muốn. Như vậy có thể sẽ dẫn đến những vấn đề không đáng có.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | <span class="token keyword">function</span> <span class="token function">makeAPICall</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Bắt đầu gọi API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// delay 2 giây</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Nhận data từ API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Gọi API thành công.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Xử lý data'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Đọc data.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Chức năng khác không liên quan đến API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token function">makeAPICall</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Output:</span> <span class="token comment">// 'Bắt đầu gọi API.'</span> <span class="token comment">// 'Xử lý data'</span> <span class="token comment">// 'Đọc data.'</span> <span class="token comment">// 'Chức năng khác không liên quan đến API.'</span> <span class="token comment">// 'Nhận data từ API.'</span> <span class="token comment">// 'Gọi data thành công.'</span> |
Hướng giải quyết cho vấn đề ở đây là viết code bất đồng bộ, đưa việc gọi API vào xử lý bất đồng bộ. Khi làm vậy thì JavaScript có thể chạy được nhiều task khác nhau và chạy cùng lúc với nhau. Khi chạy một task bất đồng bộ thì nó sẽ được đưa vào event queue do đó sẽ không block main thread.
Nếu main thread không bị block thì nó có thể thực thì được các task tiếp theo, và code của bạn sẽ tiếp tục chạy. Đến khi task bất đồng bộ được chạy xong thì nó sẽ trả về data để bạn xử lý. Có 3 cách để làm được việc này đó là callback
, Promise
và async/await
.
Callback
Cách đầu tiên và cũng là lâu đời nhất để xử lý bất đồng bộ trong JavaScript là sử dụng callbacks. Một callback là một hàm bất đồng bộ được truyền vào một hàm khác dưới dạng tham số khi gọi. Khi function bạn chạy xong thì nó sẽ “gọi lại” hàm callback được truyền vào.
Hàm callback này sẽ không được gọi, không được thực thi hay làm bất cứ điều gì cho đến khi hàm chính chạy xong. Hàm này sẽ không block main thread do đó main thread sẽ có thể làm các việc khác. Event listener chính là một trong các callback mà chúng ta thường xuyên sử dụng.
addEventListener()
nhận vào 3 tham số. Tham số đầu tiên là loại event bạn muốn lắng nghe. Tham số thứ hai chính là hàm callback mà bạn muốn chạy khi event diễn ra. Tham số cuối cùng là một object và không bắt buộc.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token comment">// tìm button có id là '#btn' trong DOM</span> <span class="token keyword">const</span> btn <span class="token operator">=</span> document<span class="token punctuation">.</span><span class="token function">querySelector</span><span class="token punctuation">(</span><span class="token string">'#btn'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">handleBtnClick</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Click!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// gắn event listener vào button,</span> <span class="token comment">// và truyền function xử lý event vào như một callback</span> <span class="token comment">// và callback này sẽ chạy khi và chỉ khi ai đó ấn vào button này.</span> btn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> handleBtnClick<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// một cách khác:</span> <span class="token comment">// viết trực tiếp callback.</span> btn<span class="token punctuation">.</span><span class="token function">addEventListener</span><span class="token punctuation">(</span><span class="token string">'click'</span><span class="token punctuation">,</span> <span class="token keyword">function</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Click!'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> |
Callback cực kì hữu dụng nếu bạn không thể biết trước bao giờ sẽ có data hoặc thời điểm hàm chính chạy xong. Lấy ví dụ về một việc gọi API, xử lý data và có delay. Gần như sẽ không thể biết trước được rằng bao giờ API mới hoàn tất, cũng như là việc xử lý xong data.
Với callback, bạn sẽ không cần phải đoán xem bao giờ thì xử lý xong. Bạn chỉ việc code theo đúng thứ tự mà bạn mong muón. Ví dụ, nếu việc xử lý API mất thời gian, thì bạn có thể cho hàm đọc data làm callback và chỉ thực thi khi nào có data. Do đó sẽ không có gì block main thread hết.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | <span class="token keyword">function</span> <span class="token function">makeAPICall</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Bắt đầu gọi API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// delay 2 giây</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Nhận data từ API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Gọi API thành công.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Xử lý data'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// Create a function to read the API data</span> <span class="token keyword">function</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Đọc data.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// Create another app function</span> <span class="token comment">// This function will be invoked</span> <span class="token comment">// right after the makeAPICall() function</span> <span class="token comment">// and before all other functions</span> <span class="token keyword">function</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Chức năng khác không liên quan đến API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token function">makeAPICall</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Output:</span> <span class="token comment">// 'Bắt đầu gọi API.'</span> <span class="token comment">// 'Chức năng khác không liên quan đến API.'</span> <span class="token comment">// 'Nhận data từ API.'</span> <span class="token comment">// 'Xử lý data'</span> <span class="token comment">// 'Đọc data.'</span> <span class="token comment">// 'Gọi data thành công'</span> |
Promise
Cách thứ hai đó để xử lý bất đồng bộ là promise. Promise là một tính năng mới được giới thiệu ở ES6, nó cung cấp một cách dễ dàng hơn để xử lý bất đồng bộ trong JavaScript.
Một Promise là một object chứa một giá trị. Giá trị này sẽ không được show ra khi bạn tạo Promise. Promise sẽ trả về giá trị này khi nó thành công hoặc thất bại. Có 3 hàm handler bạn có thể sử dụng để lấy giá trị mà Promise trả về.
Các hàm này là then()
, catch()
và finally()
. Đẻ sử dụng những hàm handler này thì ta gắn chúng vào một object Promise. Dựa vào trạng thái của Promise thì handler tương ứng sẽ được invoke.
then()
sẽ chạy khi Promise thành công. Đôi khi bạn cũng có thể sử dụng để xử lý trạng thái thất bại của Promise.catch()
sẽ chạy chỉ khi Promise thất bại.finally()
sẽ chạy khi Promise chạy xong, không quan trọng là thành công hay thất bại.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | <span class="token keyword">const</span> makeAPICall <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Bắt đầu gọi API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Nhận data từ API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'Gọi API thành công.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Xử lý data'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Đọc data.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// Hàm này sẽ chạy ngay sau Promise makeAPICall</span> <span class="token comment">// và chạy trước tất cả các hàm khác.</span> <span class="token keyword">function</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Chức năng khác không liên quan đến API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> makeAPICall <span class="token comment">// add handle cho status thành công</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">result</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// add handle cho status thất bại</span> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">error</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Có lỗi xảy ra: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>error<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// bạn có thể thêm finally() ở đây</span> <span class="token comment">// .finally(() => {})</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Output:</span> <span class="token comment">// 'Bắt đầu gọi API.'</span> <span class="token comment">// 'Chức năng khác không liên quan đến API.'</span> <span class="token comment">// 'Nhận data từ API.'</span> <span class="token comment">// 'Gọi data thành công'</span> <span class="token comment">// 'Xử lý data'</span> <span class="token comment">// 'Đọc data.'</span> |
Async/await
Cách cuối cùng để xử lý bất đồng bộ là sử dụng async/await. Async/await được giới thiệu ở ES8, chúng được cấu tạo từ 2 phần. Phần đầu tiên là function async
. Hàm này sẽ được tự động thực thi bất đồng bộ. Giá trị nó trả về là một Promise. Vì trả về Promise nên bạn sẽ phải sử dụng các handler của Promise để xử lý giá trị này.
Phần thứ hai của async/await là operator await
. Operator này sẽ được dùng cùng với một Promise. Nó sẽ khiến cho function async
tạm dừng cho đến khi Promise đó chạy xong. Ngay sau đó nó sẽ lấy gía trị của Promise mà cho function async
tiếp tục chạy.
Các function async
đều bất đồng bộ, khi bị pause bởi await
thì phần code còn lại vẫn chạy bình thường vì function đấy không block main thread. Khi Promise chạy xong thì hàm async
sẽ chạy tiếp và trả về giá trị của Promise.
Một điều quan trọng hơn là await
phải được viết trong hàm async
nếu không thì sẽ gặp lỗi syntax error
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 | <span class="token comment">// tạo một hàm async</span> <span class="token keyword">async</span> <span class="token keyword">function</span> <span class="token function">makeAPICall</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token comment">// Show notification about API call</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Bắt đầu gọi API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Create a Promise to make the API call</span> <span class="token keyword">const</span> dataPromise <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Promise</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token parameter">resolve<span class="token punctuation">,</span> reject</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">setTimeout</span><span class="token punctuation">(</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Nhận data từ API.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">resolve</span><span class="token punctuation">(</span><span class="token string">'Gọi API thành công.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">,</span> <span class="token number">2000</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token keyword">return</span> dataReceived <span class="token operator">=</span> <span class="token keyword">await</span> dataPromise <span class="token punctuation">}</span> <span class="token keyword">function</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Xử lý data'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token keyword">function</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Đọc data.'</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">;</span> <span class="token comment">// Hàm này sẽ chạy ngay sau async makeAPICall</span> <span class="token comment">// và chạy trước tất cả các hàm khác.</span> <span class="token keyword">function</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token string">'Some other function not related to API.'</span><span class="token punctuation">)</span> <span class="token punctuation">}</span> makeAPICall <span class="token comment">// add handle cho status thành công</span> <span class="token punctuation">.</span><span class="token function">then</span><span class="token punctuation">(</span><span class="token parameter">result</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>result<span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">processAPIData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token function">readTheData</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// add handle cho status thất bại</span> <span class="token punctuation">.</span><span class="token function">catch</span><span class="token punctuation">(</span><span class="token parameter">error</span> <span class="token operator">=></span> <span class="token punctuation">{</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span><span class="token template-string"><span class="token template-punctuation string">`</span><span class="token string">Có lỗi xảy ra: </span><span class="token interpolation"><span class="token interpolation-punctuation punctuation">${</span>error<span class="token interpolation-punctuation punctuation">}</span></span><span class="token string">.</span><span class="token template-punctuation string">`</span></span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token comment">// bạn có thể thêm finally() ở đây</span> <span class="token comment">// .finally(() => {})</span> <span class="token function">someOtherFunction</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token comment">// Output:</span> <span class="token comment">// 'Bắt đầu gọi API.'</span> <span class="token comment">// 'Chức năng khác không liên quan đến API.'</span> <span class="token comment">// 'Nhận data từ API.'</span> <span class="token comment">// 'Gọi data thành công'</span> <span class="token comment">// 'Xử lý data'</span> <span class="token comment">// 'Đọc data.'</span> |
Cảm ơn các bạn đã đọc bài.
Nguồn: https://blog.alexdevero.com/asynchronous-javascript-code/