ổng hợp xử lý bất đồng bộ trong Javascript – Tổng hợp xử lý bất đồng bộ trong Javascript: callback, – StuDocu

Tổng hợp xử lý bất đồng bộ trong Javascript:

callback, promise và async

SyncJavaScriptasync
Lúc trước đi phỏng vấn có một câu hỏi là hãy kể tên các phương thức
xử lý bất đồng bộ trong javascript, mình chỉ nhớ mỗ async await vì
đã đọc qua ở đâu đó rồi. Nhưng lại không nhớ cú pháp chính xác.
Nên sau buổi hôm đó mình quyết định sẽ tìm hiểu về các phương
thức xử lý bất dồng bộ trong javascript và các vấn đề liên quan. Hôm
nay mình xin viết một bài về vấn đề này.

Sync với Async

Trước khi vào vấn đề chúng ta cùng tìm hiểu xem đồng bộ và bất
đồng bộ là gì? Đồng bộ: Hiểu đơn giản thì đồng bộ có nghĩa là thực
hiện các công việc một cách tuần tự, công việc này xong thì mới
được thực hiện các công việc khác. Ví dụ có 2 công việc A và B thì
khi có nghĩa là A thực hiện xong trước rồi mới tới lượt B. Như vậy
tổng thời gian hoàn thành sẽ như bên dưới.

Điều này nó sẽ ảnh hưởng đến hiệu suất của người dùng. Giả sử một
request gửi lên server yêu cầu server thực hiện chức năng như
import file hoặc đọc ghi file thì lúc này server sẽ mất nhiều thời gian
để xử lý những việc này. Điều đó cũng đồng nghĩa với việc trong lúc
server thực hiện chức năng đó thì sẽ không thể thực hiện thêm một
hành động nào khác. Chưa kể trong lúc server đang thực hiện những

hiện việc đó thì lại có thể có nhiều request được gởi đến trong khi
server chưa thực hiện xong, điều này có thể gây crash server.

Multi-thread

Để khắc phục tình trạng này, các ngôn ngữ lập trình như C/C++,
Java,… sẽ sử dụng cơ chế đa luồng (multi-thread). Nghĩa là mỗi công
việc tốn thời gian sẽ được thực hiện trên một thread riêng biệt mà
không can thiệp vào thread chính. Bạn vẫn có thể thực hiện các công
việc tốn thời gian mà vẫn có thể bắt các sự kiện ở thread chính.

Javascript và cơ chế bất đồng bộ

Đối với javascript thì nó là ngôn ngữ là ngôn ngữ Single threed, các
bạn có thể đọc thêm single threed ở link
sau: viblo/p/javascript-single-thread-lieu-da-loi-thoi-
gAm5yxwkldb Tức là nó chỉ có 1 thredd duy nhất, nên các bạn không
thể sử dụng multi thread như những ngôn ngữ khác mà phải sử dụng
cơ chế xử lý bất đồng
bộ 

Ngoài ra thì callback còn được dùng khi các bạn sử dụng ajax,. Khi
gửi request đến server thành công và server sẽ respone về thành
công thì một hàm success sẽ được gọi. sau đó chúng ta chỉ việc viết
code để xử lý cái callback này.

Callback hell

Chúng ta đã hiểu về callback rồi, tuy nhiên trong trường hợp có quá
nhiều callback được lồng vào nhau, kiểu như là khi thực hiện xong
một callback này thì mới được thực hiện một callback khác, ví dụ
như:

Sẽ rất khó coi nếu như chương trình của chúng ta có hàng chục
callback như vậyình sẽ khó hiểu và khó maintenance hơn. Đây
chính là Callback hell và chúng ta cần tránh điều này khi lập trình. Có
nhiều cách để phòng chống callback hell, mình sẽ nói đến môt vài
cách phòng chống callback hell phổ biến.

Promise

Promise là một cơ chế trong JavaScript giúp bạn thực thi các tác vụ
bất đồng bộ mà không rơi vào callback hell hay pyramid of doom, là
tình trạng các hàm callback lồng vào nhau ở quá nhiều tầng. Các tác
vụ bất đồng bộ có thể là gửi AJAX request, gọi hàm bên trong
setTimeout, setInterval hoặc requestAnimationFrame, hay thao tác
với WebSocket hoặc Worker… Dưới đây là một callback hell điển
hình.

Promise sinh ra để xử lý kết quả của một hành động cụ thể, kết quả
của mỗi hành động sẽ là thành công hoặc thất bại và Promise sẽ
giúp chúng ta giải quyết câu hỏi "Nếu thành công thì làm gì? Nếu
thất bại thì làm gì?". Cả hai câu hỏi này ta gọi là một hành động gọi
lại (callback action).

Khi một Promise được khởi tạo thì nó có một trong ba trạng thái sau:

 Fulfilled Hành động xử lý xong và thành công
 Rejected Hành động xử lý xong và thất bại
 Pending Hành động đang chờ xử lý hoặc bị từ chối

Trong đó hai trạng thái Reject và Fulfilled ta gọi là Settled, tức là đã
xử lý xong.

Cách tạo một promise

var promise = new Promise(callback)

Trong đó callback là một function có 2 tham số truyền vào như sau:

var promise = new Promise(function(resolve, reject){

});

Trong đó: resolve: là một hàm callback xử lý cho hành động thành
công. reject là: một hàm callback xử lý cho hành động thất bại. Một
ví dụ minh họa cho việc sử dụng promise để đọc file:

Cách sử dụng asyn/await

Để sử dụng hàm async, ta cần khai báo từ khóa async ngay trước từ
khóa định nghĩa hàm. Tức là, với hàm định nghĩa với từ khóa function
ta phải khai báo ngay trước function, với hàm mũi tên (arrow
function) ta phải khai báo trước tập tham số đầu vào.

Với từ khóa async này, ta có thể đợi các Promise (thao tác bất đồng
bộ) xử lý trong hàm đó mà không tạm dùng luồng chính bằng từ
khóa await như ví dụ trên.

Kết quả trả ra của hàm async luôn là một Promise dù bạn có gọi
await – có xử lý bất đồng bộ hay không. Promise này sẽ ở trạng thái
thành công với kết quả được trả ra với 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. Như vậy,chúng ta có thể thấy bản chất của hàm
async chính là Promise.

Với Promise, ta có thể xử lý ngoại lệ với catch khá đơn giản. Tuy
nhiên cũng không dễ dàng theo dõi và dễ đọc. Nhưng với hàm async,
việc này cực kì đơn giản bằng từ khóa try catch hệt như các thao tác
đồng bộ.

Tóm tắt

Tóm lại mình xin tóm tắt một vài ý chính liên quan đến async/await
như sau:

 await luôn luôn nằm trong hàm async như ví dụ trên ( await
không thể nằm trong hàm không được khai báo từ khóa async
phía trước)