Await
Cú pháp:
// works only inside async functions let value = await promise;
await
khi được đặt trước một promise, nó sẽ đợi cho đến khi promise kết thúc và trả về kết quả. Dưới đây là một ví dụ với một promise sẽ được xử lí trong 1 giây:
async function f() { let promise = new Promise((resolve, reject) => { setTimeout(() => resolve(“done!”), 1000) }); let result = await promise; // wait until the promise resolves (*) alert(result); // “done!” } f();
Hiểu
await
theo đúng nghĩa đen thì ban đầu nó sẽ tạm dừng việc thực thi hàm cho đến khi promise được giải quyết, và sau đó nó sẽ tiếp tục khi promise đó được xử lí xong. Điều đó không tốn bất kỳ tài nguyên CPU nào, vì JavaScript có thể thực hiện các công việc khác trong thời gian chờ đợi: thực thi các tập lệnh khác, xử lý các sự kiện, v.v.
Cú pháp Async/Await
Async
Từ khóa Async được đặt trước 1 hàm làm cho hàm trả về promise.
Ví dụ:
async function myFunction() { return "Hello"; }
Tương tự như trên:
async function myFunction() { return Promise.resolve("Hello"); }
Dưới đây là cách sử dụng Promise:
myFunction().then( function(value) { /* code if successful */ }, function(error) { /* code if some error */ } );
Await
Từ khóa Await được đặt trước 1 hàm làm cho hàm chờ một promise.
let value = await promise;
Từ khóa await chỉ có thể được sử dụng bên trong một hàm không đồng bộ.
Ví dụ:
Tổng kết
Việc sử dụng
async/await
có một số ưu điểm vượt trội:
- Code dễ đọc hơn rất rất nhiều, không cần phải
then
rồi
catch
, chỉ viết như bình thường, sau đó dùng
try/catch
để bắt lỗi.- Debug dễ hơn nhiều, vì mỗi lần dùng
await
được tính là một dòng code, do đó ta có thể đặt debugger để
debug
từng dòng như thường.- Khi có lỗi,
exception
sẽ chỉ ra lỗi ở dòng số mấy chứ không chung chung là
un-resolved promise
.- Với promise hoặc
callback
, việc kết hợp
if/else
hoặc retry với code
asynchnous
là một điều gì đó khá khó chịu. Với
async/await
, việc này vô cùng dễ dàng.Vậy là series tìm hiểu về
promise,
async
await
của chúng ta đã khép lại. Các bạn truy cập Fanpage của Suntech để tìm kiếm các thông tin về khóa học và việc làm tại đây. Hẹn gặp lại các bạn trong các bài học khác!
Trong lập trình JavaScript, việc xử lý các tác vụ bất đồng bộ (asynchronous tasks) là rất phổ biến và quan trọng. Các tác vụ bất đồng bộ bao gồm việc gửi yêu cầu HTTP, xử lý tập tin, truy vấn cơ sở dữ liệu, và nhiều hơn nữa. Async/Await là một cơ chế mới trong JavaScript giúp xử lý các tác vụ bất đồng bộ một cách dễ dàng hơn. Trong bài viết này, chúng tôi sẽ giải thích chi tiết về cơ chế này, từ cách nó hoạt động đến cách sử dụng nó để xử lý các tác vụ bất đồng bộ.
Async/Await là một cơ chế mới được giới thiệu trong ES2017 để giải quyết các vấn đề liên quan đến việc xử lý các tác vụ bất đồng bộ trong JavaScript. Cơ chế này cung cấp cho chúng ta cách viết mã đơn giản hơn và dễ hiểu hơn so với việc sử dụng Promise.
Các tác vụ bất đồng bộ trong JavaScript thường được xử lý bằng cách sử dụng Promise. Tuy nhiên, việc sử dụng Promise có thể dẫn đến các vấn đề liên quan đến callback hell, nesting callbacks và các vấn đề về việc xử lý lỗi. Async/Await giúp giải quyết các vấn đề này bằng cách cho phép chúng ta viết mã dễ đọc hơn và giải quyết các vấn đề liên quan đến xử lý lỗi.
Trong Async/Await, chúng ta sử dụng các từ khóa “async” và “await” để đánh dấu hàm và đợi các giá trị trả về từ các tác vụ bất đồng bộ.
Video học lập trình mỗi ngày
Link toàn bộ Series bài viết:[Series Callback Javascript] Phần 1: Giới Thiệu Callbacks.
[Series Callback Javascript] - Phần 2: Promise Là Gì? Khi Nào Sử Dụng Promise ?
Series Callback Javascript: Phần 3 : Async/Await Là Gì? Khác Gì Với Promise Trong Javascript?
[ Tự Học Javascript] - Nếu Có Async/Await Rồi Thì Promise Có Còn Lỗi Thời? Không Cần Thiết Dùng Đến Hay Không?
Wow. Khi các bạn đọc đến phần 3 này tôi cá rằng các bạn giờ đây cũng đã hiểu khá sâu về CallBacks trong javascript. Và các bạn cũng đã khá thành thục về callback or promise.Thật ra, rất lâu rồi các lập trình viên javascript rất khổ sở khi có những nhiệm vụ phải xoay sở với chiều sâu của một func, lúc đó sự lặp lại của calkback là một nỗi kinh hoàng và khổ sở.Rất may sau đó chúng ta phải nói lời cám ơn tới các nhà phát triển đồng thời cảm ơn promise đã kịp thời xua tan những nỗi kinh hoàng đó. Và chúng thay thế một cách ấn tượng để hầu hết cộng đồng nhanh chóng chuyển sang sử dụng chúng. Cụ thể là Async/await với sự bổ sung tốt hơn nữa zô zô..Đừng quên hiểu khái niệm callback là gì ở phần 1, và promise là gì ở phần hai nhé các bạn.
-- Phần 1: Callback truyền thống là gì?
-- Phần 2: Promise là gì? Ok, chúng ta bây giờ sẽ giới thiệu về Async/await.1 - Async/await là gì?
Async / Await là một tính năng JavaScript được dự đoán từ lâu, giúp làm việc với các chức năng không đồng bộ thú vị hơn và dễ hiểu hơn nhiều. Nó được xây dựng dựa trên Promise và tương thích với tất cả các API dựa trên Promise hiện có.Hai từ khoá thôi nhưng vô cùng quan trọng, nó giúp các coder javascript chuyển hướng một cách ngoạn mục trong việc đồng bộ và không đồng bộ.- Async - Khai báo (async function someName(){...})+ Tự động chuyển một function thành một Promise()+ Các chức năng Async cho phép sử dụng await.- Await - tạm dừng thực thi các chức năng không đồng bộ (var result = await someAsyncCall();)+ Await chỉ được hoạt động và sử dụng khi có khai báo Async. Không khai báo lỗi ráng chịu.+ Await nó chỉ hoạt động với Promise chứ không thèm chơi với các function có callbackOk nhé! Chỉ đơn giản vậy thôi mà hay dữ dằn.Giờ đi vào ví dụ cụ thể. Tôi sẽ gộp phần 1, phần 2, và phần 3 cung cấp cho các bạn một ví dụ từ callback đến promise và đến async/await.Nhớ đọc phần 1 và phần 2 rồi mới xem ví dụ này, nếu ko tẩu hoả nhập ma. Không ai chịu trách nhiệm. ^-^Phần quan trọng của bài viết có thể bỏ qua các dòng khác nhưng không thể bỏ qua các ví dụ này
callback - Đây chính là dạng callback truyền thống, reo rắc nỗi kinh hoàng cho coders 😀
promise - Còn đây chính là promise thần thánh mà tôi đã nói ở phần hai - sử dụng Promise()
Và cuối cùng đây chính là phần 3 về async/awaitQua 3 ví dụ các bạn thấy đó, trong quá trình phát triền js các developers không ngại gian khô để tối ưu hoá một cách triệt để để giúp các coder có thể thực hiện các step một cách dễ dàng trong qua trình xây dựng một dự án. Khai báo một chức năng là async sẽ đảm bảo rằng nó luôn trả về một Promise để bạn không phải lo lắng về điều đó nữa.
Vậy câu hỏi đặt ra ở đây nhé: Nếu có async/await rồi thì Promise có còn lỗi thời? không cần thiết dùng đến hay không? Ở bài tiếp theo tôi sẽ cho các bạn câu trả lời mà hầu hết các LTV đều có thể chưa có câu trả lời rõ ràng hoặc chưa phân biệt được khi nào sử dụng hai loại đó. Và quan trọng hơn là lúc nào sử dụng async/await hay promise để đạt hiệu suất tối ưu.Mời các bạn đón đọc bài tiếp theo rất thú vị : Nếu có async/await rồi thì Promise có còn lỗi thời? không cần thiết dùng đến hay không?
Link toàn bộ Series bài viết:[Series Callback Javascript] Phần 1: Giới Thiệu Callbacks.
[Series Callback Javascript] - Phần 2: Promise Là Gì? Khi Nào Sử Dụng Promise ?
Series Callback Javascript: Phần 3 : Async/Await Là Gì? Khác Gì Với Promise Trong Javascript?
[ Tự Học Javascript] - Nếu Có Async/Await Rồi Thì Promise Có Còn Lỗi Thời? Không Cần Thiết Dùng Đến Hay Không?
Tham khảo thêm tại : https://www.toptal.com/javascript/asynchronous-javascript-async-await-tutorial
Trong trường hợp bạn đã quên mất, Node.js đã hỗ trợ async/await kể từ phiên bản 7.6. Nếu bạn chưa thử qua, bài viết này sẽ liệt kê các lý do cùng ví dụ để giải thích tại sao bạn nên chọn nó.
Kết luận và bài viết có liên quan
Async/Await là một cơ chế mạnh mẽ trong JavaScript giúp xử lý các tác vụ bất đồng bộ dễ dàng hơn và giải quyết các vấn đề liên quan đến callback hell và việc xử lý lỗi. Chúng ta có thể sử dụng từ khóa “async” để đánh dấu hàm bất đồng bộ và từ khóa “await” để đợi các giá trị trả về từ các tác vụ bất đồng bộ. Chúng ta cũng có thể sử dụng câu lệnh try/catch để xử lý các lỗi có thể xảy ra trong quá trình xử lý các tác vụ bất đồng bộ. Hy vọng rằng bài viết này đã giúp bạn hiểu rõ hơn về cơ chế Async/Await trong JavaScript.
Tải xuống
Tài liệu
Nhằm phục vụ mục đích học tập Offline của cộng đồng, Kteam hỗ trợ tính năng lưu trữ nội dung bài học Async/Await là gì? dưới dạng file PDF trong link bên dưới.
Ngoài ra, bạn cũng có thể tìm thấy các tài liệu được đóng góp từ cộng đồng ở mục TÀI LIỆU trên thư viện Howkteam.com
Đừng quên like và share để ủng hộ Kteam và tác giả nhé!
Error handling
Nếu một promise được xử lí bình thường, thì
await promise
sẽ trả về kết quả. Nhưng trong trường hợp bị từ chối, nó sẽ tạo ra lỗi, giống như thể có một câu lệnh
throw
ở dòng đó. Ví dụ
async function f() { await Promise.reject(new Error("Whoops!")); }
Nó sẽ bị lỗi như dưới đây trong trường hợp bị từ chối:
async function f() { throw new Error("Whoops!"); }
Trong các tình huống thực tế, promise có thể mất một thời gian trước khi bị từ chối. Trong trường hợp đó sẽ có một khoảng thời gian trễ trước khi
await
sinh ra một lỗi. Một điều tuyệt vời khác về Async / Await là nó cho phép chúng ta bắt các lỗi không mong đợi bằng cách sử dụng try / catch
async function f() { try { let response = await fetch('http://no-such-url'); } catch(err) { alert(err); // TypeError: failed to fetch } } f();
-
Mệnh đề
catch
sẽ xử lý các lỗi gây ra bởi các hàm bất đồng bộ hoặc bất kỳ lỗi nào chúng ta có thể đã viết bên trong khối
try
.
async function f() { try { let response = await fetch('/no-user-here'); let user = await response.json(); } catch(err) { // catches errors both in fetch and response.json alert(err); } } f();
Nếu chúng ta không có
try..catch
, thì
promise
được tạo bởi lệnh gọi của hàm bất đồng bộ
f()
sẽ bị từ chối. Vì vậy chúng ta cần thêm
.catch
vào để xử lý nó:
async function f() { let response = await fetch('http://no-such-url'); } // f() becomes a rejected promise f().catch(alert); // TypeError: failed to fetch // (*)
Nếu chúng ta quên thêm vào .catch đó, thì chúng ta sẽ gặp lỗi promise. Chúng ta có thể bắt gặp các lỗi như vậy bằng cách sử dụng
unhandled rejection
như được mô tả trong bài Error handling with promise
Thảo luận
Nếu bạn có bất kỳ khó khăn hay thắc mắc gì về khóa học, đừng ngần ngại đặt câu hỏi trong phần bên dưới hoặc trong mục HỎI & ĐÁP trên thư viện Howkteam.com để nhận được sự hỗ trợ từ cộng đồng.
Nội dung bài viết
Khóa học
Trong thời gian gần đây, JavaScript luôn là ngôn ngữ rất nhiều lập trình viên và sinh viên IT đang quan tâm và bàn tán vì tính linh hoạt, đa năng và cơ hội nghề nghiệp hấp dẫn mà ngôn ngữ này mang lại. Với sự phát triển nhanh các tính năng mới của JavaScript khiến nhiều người đang nghiên cứu cũng khó nhớ hết những tính năng và hiểu bản chất cụ thể của nó.
Thông qua khóa học SỔ TAY JAVASCRIPT, đây chỉ là những ghi chép mà Kteam tổng hợp như để có thể nghiên cứu lại khi cần thiết và giúp các bạn học hiểu được những tính năng JavaScript hiện nay.
Nội dung bài viết
Những điều cần lưu ý khi sử dụng Async/Await
Chúng ta không thể sử dụng Await bên trong các hàm thông thường
Ví dụ:
function firstAsync() { let promise = Promise.resolve(10); let result = await promise; // Syntax error }
Để hàm trên hoạt động bình thường, chúng ta cần thêm từ khóa async trước function firstAsync();
Async/Await thực hiện tuần tự
Đây không hẳn là điều xấu, nhưng thực hiện song song sẽ nhanh hơn nhiều.
Ví dụ:
async function sequence() { await promise1(50); // Wait 50ms… await promise2(50); // …then wait another 50ms. return "done!"; }
Đoạn code trên mất 100ms để hoàn thành, không phải một lượng thời gian lớn nhưng vẫn chậm. Điều này xảy ra là do nó đang diễn ra theo trình tự. Hai hàm được trả lại, cả hai đều mất 50ms để hoàn thành. Hàm thứ hai chỉ thực hiện sau khi hàm đầu tiên được giải quyết. Đây không phải là một thực tiễn tốt, vì các yêu cầu lớn có thể rất tốn thời gian. Chúng ta phải thực hiện song song.
Chúng ta có thể làm được điều đó bằng cách sử dụngPromise.all()
Theo MDN: “Phương thức Promise.all(iterable) trả ra một Promise mới và promise mới này chỉ được kết thúc khi tất cả các promise trong iterable kết thúc hoặc có một promise nào đó xử lý thất bại. Kết quả của promise mới này là một mảng chứa kết quả của tất cả các promise theo đúng thứ tự hoặc kết quả lỗi của promise gây lỗi.”
Ví dụ:
async function sequence() { await Promise.all([promise1(), promise2()]); return "done!"; }
Hàm Promise.all() giải quyết khi tất cả các lời hứa bên trong có thể lặp được giải quyết và sau đó trả về kết quả.
Async functions
Async
functions là hàm bất đồng bộ. Nó có thể được sử dụng như sau:
async function f() { return 1; }
Một function luôn trả về một promise. Các giá trị khác được bao bọc trong một promise đã được giải quyết tự động. Ví dụ, hàm này trả về một promise đã giải quyết với kết quả là
async function f() { return 1; } f().then(alert); // 1
Chúng ta có thể trả lại một
promise
theo cách khác như sau:
async function f() { return Promise.resolve(1); } f().then(alert); // 1
Vì vậy, hãy đảm bảo rằng hàm
async
trả về một promise. Nhưng không chỉ có vậy. Chúng ta có thể dùng
await
. Nó chỉ hoạt động bên trong các
async
functions.
Cú pháp
Giả sử một hàm
getJSON
trả về một promise, promise đó chứa 1 vài đối tượng JSON. Ta cần gọi hàm đó, log các đối tượng JSON ra, sau đó trả về
"done"
.
Đoạn code sau miêu tả quá trình trên, sử dụng promise.
const makeRequest = () => getJSON() .then(data => { console.log(data) return "done" }) makeRequest()
Còn đây là đoạn code sử dụng async/await:
const makeRequest = async () => { console.log(await getJSON()) return "done" } makeRequest()
Có 1 vài điểm khác biệt cần để ý:
-
Hàm có thêm từ khóa
async
phía trước. Từ khóa
await
chỉ được sử dụng bên trong hàm được định nghĩa với
async
. Bất cứ hàm
async
nào cũng sẽ trả về 1 promise một cách không tường minh, và giá trị resolve của promise sẽ là bất cứ cái gì mà hàm return (trong trường hợp này là chuỗi
"done"
). -
Nhận xét trên cũng đồng nghĩa với việc ta không thể sử dụng await phía trước đoạn code chứa từ khóa
async
// this will not work in top level // await makeRequest() // this will work makeRequest().then((result) => { // do something })
await getJSON()
có nghĩa là lời gọi
console.log
sẽ chờ đến khi promise
getJSON()
được xử lý và trả về giá trị.
Cách sử dụng Async/Await
2.1 Sử dụng Async/Await với hàm async
Để sử dụng Async/Await, chúng ta cần đánh dấu hàm bằng từ khóa “async”. Việc đánh dấu hàm này cho phép chúng ta sử dụng từ khóa “await” để đợi các giá trị trả về từ các tác vụ bất đồng bộ.
Ví dụ:
async function getData() { const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); const data = await response.json(); return data; } getData().then(data => console.log(data));
Ở đoạn mã trên, chúng ta sử dụng từ khóa “async” để đánh dấu hàm “getData” là một hàm bất đồng bộ. Sau đó, chúng ta sử dụng từ khóa “await” để đợi response từ phương thức fetch() trước khi tiếp tục xử lý các dòng tiếp theo. Sau đó, chúng ta lại sử dụng từ khóa “await” để đợi phương thức json() hoàn thành việc chuyển đổi response thành một đối tượng JSON. Cuối cùng, chúng ta trả về đối tượng JSON được phân tích từ response.
2.2 Sử dụng Async/Await với try/catch
Async/Await cung cấp cho chúng ta cách xử lý lỗi tốt hơn khi sử dụng tác vụ bất đồng bộ. Chúng ta có thể sử dụng câu lệnh try/catch để xử lý các lỗi xảy ra trong quá trình xử lý các tác vụ bất đồng bộ.
Ví dụ:
async function getData() { try { const response = await fetch('https://jsonplaceholder.typicode.com/todos/1'); const data = await response.json(); return data; } catch (error) { console.log(error); } } getData();
Ở đoạn mã trên, chúng ta sử dụng câu lệnh try/catch để xử lý các lỗi có thể xảy ra trong quá trình xử lý các tác vụ bất đồng bộ. Nếu có lỗi xảy ra, chúng ta sẽ ghi log ra console để thông báo cho người dùng.
Tại sao nên dùng Async/Await?
Ngắn gọn và sạch sẽ
Ưu điểm đơn giản nhất chính là số lượng code ta cần viết đã giảm đi đáng kể. Không cần phải then rồi catch gì cả, chỉ viết như code chạy tuần tự, sau đó dùng try/catch thông thường để bắt lỗi.
Xử lí lỗi
Async/await giúp ta xử lý cả error đồng bộ lẫn error bất đồng bộ theo cùng 1 cấu trúc. Tạm biệt try/catch. Với đoạn code dưới dùng promise, try/catch sẽ không bắt được lỗi nếu JSON.parselỗi do nó xảy ra bên trong promise. Ta cần gọi .catch bên trong promise và lặp lại code xử lý error, điều mà chắc chắn sẽ trở nên rắc rối hơn cả console.logtrong đoạn code production.
const makeRequest = () => { try { getJSON() .then(result => { // this parse may fail const data = JSON.parse(result) console.log(data) }) // uncomment this block to handle asynchronous errors // .catch((err) => { // console.log(err) // }) } catch (err) { console.log(err) }
Bây giờ hãy nhìn vào đoạn code sử dụng async/await. Khối catchgiờ sẽ xử lý các lỗi parsing.
const makeRequest = async () => { try { // this parse may fail const data = JSON.parse(await getJSON()) console.log(data) } catch (err) { console.log(err) } }
Câu lệnh điều kiện
Hãy tưởng tượng một cái gì đó giống như đoạn mã bên dưới tìm nạp một số dữ liệu và quyết định xem nó có nên trả lại dữ liệu đó hay không hoặc lấy thêm chi tiết dựa trên một số giá trị trong dữ liệu.
const makeRequest = () => { return getJSON() .then(data => { if (data.needsAnotherRequest) { return makeAnotherRequest(data) .then(moreData => { console.log(moreData) return moreData }) } else { console.log(data) return data } }) }
Chỉ nhìn vào đoạn code trên thôi cũng đã khiến bạn đau đầu. Thật dễ dàng bị lạc trong tất cả các câu lệnh lồng nhau (6 cấp độ), dấu ngoặc nhọn và trả về chỉ cần thiết để truyền tải kết quả cuối cùng cho đến hàm chính.
Khi sử dụng async/await, ta sẽ có đoạn code mới dễ đọc hơn.
const makeRequest = async () => { const data = await getJSON() if (data.needsAnotherRequest) { const moreData = await makeAnotherRequest(data); console.log(moreData) return moreData } else { console.log(data) return data } }
Với promise hoặc callback, việc kết hợp if/else hoặc retry với code asynchnous là một cực hình vì ta phải viết code lòng vòng, rắc rối. Với async/await, việc này vô cùng dễ dàng.
Ưu điểm của Async/await là gì?
Code ngắn và sạch hơn
Đơn giản nhất chính là số lượng code ta cần viết đã giảm đi đáng kể. Trong ví dụ trên, rõ ràng rằng ta đã tiết kiệm được rất nhiều dòng code. Ta không cần viết
.then
, tạo 1 hàm anonimous để xử lý response, hay là đặt tên
data
cho 1 biến ta không sử dụng. Ta tránh được các khối code lồng nhau. Những lợi ích nho nhỏ này sẽ tích tụ dần dần trong những đoạn code lớn, những project thật và sẽ trở nên rất đáng giá.
Error handling
Async/await giúp ta xử lý cả error đồng bộ lẫn error bất đồng bộ theo cùng 1 cấu trúc. Tạm biệt
try/catch
. Với đoạn code dưới dùng promise,
try/catch
sẽ không bắt được lỗi nếu
JSON.parse
lỗi do nó xảy ra bên trong promise. Ta cần gọi
.catch
bên trong promise và lặp lại code xử lý error, điều mà chắc chắn sẽ trở nên rắc rối hơn cả
console.log
trong đoạn code production.
const makeRequest = () => { try { getJSON() .then(result => { // this parse may fail const data = JSON.parse(result) console.log(data) }) // uncomment this block to handle asynchronous errors // .catch((err) => { // console.log(err) // }) } catch (err) { console.log(err) } }
Bây giờ hãy nhìn vào đoạn code sử dụng async/await. Khối
catch
giờ sẽ xử lý các lỗi parsing.
const makeRequest = async () => { try { // this parse may fail const data = JSON.parse(await getJSON()) console.log(data) } catch (err) { console.log(err) } }
Câu lệnh điều kiện
Hãy xem thử 1 đoạn code như dưới đây. Đoạn code này sẽ fetch dữ liệu và quyết định trả về giá trị hay là lấy thêm dữ liệu.
const makeRequest = () => { return getJSON() .then(data => { if (data.needsAnotherRequest) { return makeAnotherRequest(data) .then(moreData => { console.log(moreData) return moreData }) } else { console.log(data) return data } }) }
Đoạn code đã dần dần giống với mô hình “xyz hell” mà ta thường thấy. Tổng cộng code có 6 level nested. Khi sử dụng async/await, ta sẽ có đoạn code mới dễ đọc hơn.
const makeRequest = async () => { const data = await getJSON() if (data.needsAnotherRequest) { const moreData = await makeAnotherRequest(data); console.log(moreData) return moreData } else { console.log(data) return data } }
Giá trị intermediate
Hẳn bạn đã từng lâm vào tính huống sau: bạn cần gọi
promise1
, sau đó sử dụng giá trị nó trả về để gọi
promise2
cuối cùng sử dụng kết quả trả về của cả 2 promise trên để gọi
promise3
. Code của bạn sẽ thành ra thế này.
const makeRequest = () => { return promise1() .then(value1 => { // do something return promise2(value1) .then(value2 => { // do something return promise3(value1, value2) }) }) }
Nếu
promise3
không yêu cầu tham số
value1
, promise sẽ bớt lớp nest đi 1 chút. Nếu bạn theo chủ nghĩa cầu toàn, bạn có thể giải quyết bằng cách wrap cả 2 giá trị value1 và value2 bằng
Promise.all
tránh được các lớp nest giống như đoạn code dưới.
const makeRequest = () => { return promise1() .then(value1 => { // do something return Promise.all([value1, promise2(value1)]) }) .then(([value1, value2]) => { // do something return promise3(value1, value2) }) }
Phương pháp này đã hi sinh tính ngữ nghĩa để đổi lấy tính dễ đọc của code. Đơn giản vì chả có lý do gì mà
value1
&
value2
được đặt chung vào 1 mảng, ngoại trừ việc làm như thế sẽ tránh được promise bị nest.
Tuy nhiên cái logic này trở nên cực kì ngớ ngẩn khi ta sử dụng async/await.
const makeRequest = async () => { const value1 = await promise1() const value2 = await promise2(value1) return promise3(value1, value2) }
Error Stack
Hình dung 1 đoạn code gọi đến nhiều promise theo chuỗi. Tại 1 vị trí nào đó, đoạn code sẽ quăng ra 1 error.
const makeRequest = () => { return callAPromise() .then(() => callAPromise()) .then(() => callAPromise()) .then(() => callAPromise()) .then(() => callAPromise()) .then(() => { throw new Error("oops"); }) } makeRequest() .catch(err => { console.log(err); // output // Error: oops at callAPromise.then.then.then.then.then (index.js:8:13) })
Error Stack trả về từ chuỗi promise không thể giúp ta xác định error xảy ra ở đâu. Tệ hơn nữa, nó còn làm ta hiểu lầm rằng lỗi nằm ở hàm
callAPromise
Tuy nhiên, với async/await, Error Stack sẽ chỉ ra được hàm nào chứa lỗi.
const makeRequest = async () => { await callAPromise() await callAPromise() await callAPromise() await callAPromise() await callAPromise() throw new Error("oops"); } makeRequest() .catch(err => { console.log(err); // output // Error: oops at makeRequest (index.js:7:9) })
Khi bạn phát triển ứng dụng trên môi trường local, điều này thoạt nhìn không có quá nhiều tác dụng. Tuy nhiên với production server, nó lại rất hữu ích với Error Logs. Với những tình huống đó, biết được error xảy ra trong
makeRequest
sẽ tốt hơn rất nhiều khi được báo rằng error nằm trong
then
phía sau
then
phía sau
then
….
Debug
Điều tuyệt vời cuối cùng khi bạn làm việc với async/await đó là việc debug trở nên rất đơn giản. Debug với Promise chưa bao giờ là công việc dễ chịu vì 2 lý do sau:
1/ Bạn không thể đặt breakpoint trong arrow function trả về expression.
2/ Nếu bạn đặt breakpoint bên trong khối
.then
và sử dụng short-cut debug như step-over, trình debug sẽ không chuyển đến khối
.then
kế tiếp bởi vì nó chỉ “step” ở các đoạn code đồng bộ. Với async/await, bạn không cần arrow function quá nhiều nữa, bạn hoàn toàn có thể step qua lời gọi await y như với code đồng bộ.
Nội dung
Để theo dõi bài này tốt nhất, bạn nên xem qua bài:
- Sổ tay Javascript
- ECMAScript là gì?
- Node.js là gì?
- Cơ chế bất đồng bộ trong Javascript
- Node.js hoạt động như thế nào?
- Promise là gì?
Bài này sẽ giới thiệu những nội dung sau:
- Async/Await là gì?
- Async/Await và Promise
- Cách sử dụng Async/Await hiệu quả
Giải Thích về Async/Await Javascript trong 10 phút
Bài đăng này đã không được cập nhật trong 3 năm
-
Trong một thời gian rất dài, chúng ta phải dựa vào callbacks để làm việc với các đoạn code bất đồng bộ trong javascript. Kết quả là, rất nhiều người trong chúng ta đã có những trải nghiệm kinh khủng khi phải đối mặt với các hàm trông như thế này.
-
Callback có rất nhiều nhược điểm. Khi ta có nhiều thao tác bất đồng bộ, các callback phải chờ nhau thực hiện, thời gian để hoàn thành sẽ bị kéo dài hơn. Ngoài ra, việc viết các callback lồng nhau cũng làm cho mã nguồn của ta rắc rối và khó bảo trì.
-
Thật may mắn, trong phiên bản ES6 , JavaScript đã được bổ xung thêm ( .then() ) Promise. Nó là một thay thế tuyệt vời cho callbacks và hầu hết cộng đồng nhanh chóng chuyển sang sử dụng nó để thay thế cho callbacks. Code mới của chúng ta gần giống với code cũ, kết quả là trông dễ theo dõi và bảo trì hơn. Tuy nhiên các vấn đề của callback vẫn chưa được giải quyết triệt để.
-
Cuối cùng, trong phiên bản ES7 gần đây nhất, Async / Await đã được bổ xung để việc viết code bất đồng bộ trong JavaScript tốt hơn, code dễ nhìn hơn và dễ sử dụng hơn.
Async / Await là gì?
-
Async / Await là một tính năng của JavaScript giúp chúng ta làm việc với các hàm bất đồng bộ theo cách thú vị hơn và dễ hiểu hơn. Nó được xây dựng trên Promises và tương thích với tất cả các Promise dựa trên API. Trong đó:
-
Async - khai báo một hàm bất đồng bộ (async function someName(){...}).
- Tự động biến đổi một hàm thông thường thành một Promise.
- Khi gọi tới hàm async nó sẽ xử lý mọi thứ và được trả về kết quả trong hàm của nó.
- Async cho phép sử dụng Await.
-
Await - tạm dừng việc thực hiện các hàm async. (Var result = await someAsyncCall ()
.
- Khi được đặt trước một Promise, nó sẽ đợi cho đến khi Promise kết thúc và trả về kết quả.
- Await chỉ làm việc với Promises, nó không hoạt động với callbacks.
- Await chỉ có thể được sử dụng bên trong các function async.
Dưới đây là một ví dụ đơn giản mà hy vọng sẽ rõ ràng những điều trên:
-
Giả sử chúng ta muốn lấy một số tệp JSON từ máy chủ của mình. Chúng ta sẽ viết một hàm sử dụng thư viện axios và gửi yêu cầu HTTP GET đến Https://tutorialzine.com/misc/files/example.json . Chúng ta phải chờ đợi phản hồi từ máy chủ, đây là một yêu cầu HTTP không đồng bộ.
-
Dưới đây chúng ta sẽ viết cùng một chức năng với 2 cách khác nhau: cách thứ 1 với Promises, và cách thứ 2 với Async / Await
// cách 1: function getJSON() { // To make the function blocking we manually create a Promise. return new Promise( function(resolve) { axios.get('https://tutorialzine.com/misc/files/example.json') .then( function(json) { // The data from the request is available in a .then block // We return the result using resolve. resolve(json); }); }); } // cách 2: // Async/Await approach // The async keyword will automatically create a new Promise and return it. async function getJSONAsync() { // The await keyword saves us from having to write a .then() block. let json = await axios.get('https://tutorialzine.com/misc/files/example.json'); // The result of the GET request is available in the json variable. // We return it just like in a regular synchronous function. return json; }
- Cả hai hàm bên trên đều thực hiện một chức năng hoàn toàn giống nhau - cả hai đều trả về Promises và giải quyết với phản hồi JSON từ axios. Tuy nhiên, phiên bản Async / Await ngắn hơn và dễ đọc hơn.
- Chúng ta có thể gọi hàm async của chúng ta như sau:
getJSONAsync().then( function(result) { // Do something with result. });
Vậy khi có Async / Await có làm cho promises lỗi thời?
-
Không hoàn toàn. Khi làm việc với Async / Await, thật ra chúng ta vẫn đang sử dụng ngầm Promises. Vì thế, kể cả khi đang sử dụng Async / Await cần một sự hiểu biết tốt về Promises sẽ rất tốt cho chúng ta.
-
Ngoài ra, có những trường hợp mà Async / Await không sử dụng được và chúng ta phải sử dụng Promises. Ví dụ như khi chúng ta cần gọi nhiều thao tác bất đồng bộ và chờ cho tất cả chúng kết thúc. Nếu chúng ta thử và làm điều này với async và await, Điều gì sẽ xảy ra: Hãy xem ví dụ dưới đây các bạn sẽ thấy
async function getABC () { let A = await getValueA(); // getValueA takes 2 second to finish let B = await getValueB(); // getValueB takes 4 second to finish let C = await getValueC(); // getValueC takes 3 second to finish return A*B*C; }
- Mỗi lần gọi tới hàm await sẽ đợi cho đến khi hàm await trước đó kết thúc. Vì các wait sẽ đợi và thực hiện tuần tự từng cái một, toàn bộ chức năng sẽ mất 9 giây để thực hiện xong hàm từ đầu đến cuối (2 + 4 + 3).
- Đây không phải là một giải pháp tối ưu vì A, B và C không phụ thuộc vào nhau, chúng ta không cần biết giá trị của A trước khi chúng ta có được B. Vì vậy, chúng ta có thể lấy chúng cùng một lúc và thời gian chờ đợi sẽ được giảm bớt đi.
- Trong trường hợp như thế này, sử dụng Promise sẽ thích hợp hơn. Để gửi tất cả các yêu cầu cùng lúc, chúng ta sử dụng Promise.all(). Việc sử dụng Promise.all() sẽ đảm bảo chúng ta có tất cả các kết quả trước khi tiếp tục thực thi code, nhưng việc gọi đến các hàm bất đồng bộ sẽ được chạy song song mà không phải tuần tự từng cái một.
async function getABC () { // Promise.all() allows us to send all requests at the same time. let results = await Promise.all([ getValueA, getValueB, getValueC ]); return results.reduce((total,value) => total * value); }
- Bằng cách này, thời gian thực thi hàm sẽ mất it hơn. hàm getValueA và getValueC sẽ thực hiện xong trước khi getValueB xong. Thay vì phải mất 9 giây để chờ từng hàm trả về giá trị như trên, chúng ta sẽ chỉ mất 4 giây để chờ cả 3 hàm trả về giá trị.
Xử lý lỗi trong Async / Await
- Một điều tuyệt vời khác về Async / Await là nó cho phép chúng ta bắt các lỗi không mong đợi bằng cách sử dụng try / catch. Chúng ta chỉ cần để các await call của chúng ta vào trong khối try/catch như sau:
async function doSomethingAsync(){ try { // This async call may fail. let result = await someAsyncCall(); } catch(error) { // If it does we will catch the error here. } }
-
Mệnh đề catch sẽ xử lý các lỗi gây ra bởi các hàm bất đồng bộ hoặc bất kỳ lỗi nào chúng ta có thể đã viết bên trong khối try.
-
Trong một vài tình huống, chúng ta cũng có thể bắt các lỗi khi đang thực hiện function async. Vì tất cả các hàm async đều trả về Promises, chúng ta chỉ cần gọi thêm hàm .catch() khi gọi chúng.
// Async function without a try/catch block. async function doSomethingAsync(){ // This async call may fail. let result = await someAsyncCall(); return result; } // We catch the error upon calling the function. doSomethingAsync(). .then(successHandler) .catch(errorHandler);
- Dựa vào các tình huống cụ thể, chúng ta sẽ sử dụng try/catch hoặc .catch() để bắt và xử lý lỗi. Tuy nhiên, chúng ta không nên sử dụng cả 2 cùng một lúc vì nó có thể dẫn đến các vấn đề không mong muốn.
Hỗ trợ trình duyệt
- Async / Await có thể sử dụng trong hầu hết các trình duyệt chính, ngoại trừ IE11 - tất cả các trình duyệt sẽ nhận ra mã async / await của bạn mà không cần các thư viện bên ngoài.
- Nếu các bạn dùng Node cũng có sử dụng async từ Node 8 trở lên. Nó sẽ trở thành LTS vào cuối năm nay.
- Nếu cái này không đáp ứng được nhu cầu của bạn, cũng có một số trình chuyển đổi JS như Babel và TypeScript và thư viện Node.js async/await cung cấp các phiên bản nền tảng riêng của tính năng này.
Phần kết luận
-
Với việc bổ sung Async / Await trong ngôn ngữ JavaScript có một bước nhảy vọt về khả năng dễ đọc và dễ sử dụng cho người mới bắt đầu với các lập trình JavaScript và người đã có kinh nghiệm.
-
Một số chia sẻ có mình chỉ mang tính chất cá nhân, có thể chưa chính xác, các bạn cứ cmt , chia sẻ những gì em, mình chưa đúng ạ
-
Link tham khảo:
All rights reserved
Async/Await hoạt động như thế nào trong JS
Bài đăng này đã không được cập nhật trong 2 năm
Mở đầu
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.
Để 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.
Với bất đồng bộ, việc các sự kiện, công việc hoạt động song song không gây ảnh hưởng tới luồng công việc chính. Điều này sẽ tối ưu được thời gian chờ, qua đó làm giảm tổng thời gian cần để hoàn thành một nhiệm vụ. Nhưng kết quả của công việc thực hiện sau có thể được trả về trước kết quả của công việc chạy trước nó, do vậy kết quả trả về cuối cùng có thể sẽ không theo thứ tự đã định sẵn, yêu cầu chúng ta cần kiểm soát chặt chẽ hơn.
Chúng ta có 3 cách để xử lý việc này : callback, promise, asyn await.
Callback có rất nhiều nhược điểm. Khi ta có nhiều thao tác bất đồng bộ, các callback phải chờ nhau thực hiện, thời gian để hoàn thành sẽ bị kéo dài hơn. Ngoài ra, việc viết các callback lồng nhau cũng làm cho mã nguồn của ta rắc rối và khó bảo trì.
Trong phiên bản ES6 , JavaScript đã được bổ xung thêm ( .then() ) Promise. Nó là một thay thế tuyệt vời cho callbacks và hầu hết cộng đồng nhanh chóng chuyển sang sử dụng nó để thay thế cho callbacks. Code mới của chúng ta gần giống với code cũ, kết quả là trông dễ theo dõi và bảo trì hơn. Tuy nhiên, dùng promise đôi khi ta vẫn thấy hơi khó chịu vì phải truyền callback vào hàm then và catch. Code cũng sẽ hơi dư thừa và khó debug, vì toàn bộ các hàm then chỉ được tính là 1 câu lệnh nên không debug riêng từng dòng được.
Cuối cùng, trong phiên bản ES7 gần đây nhất, Async / Await đã được bổ xung để việc viết code bất đồng bộ trong JavaScript tốt hơn, code dễ nhìn hơn và dễ sử dụng hơn.
Async/Await
Async/await đượ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.
1. Async functions
Phần quan trọng nhất của Async functions là async key. Điều này sẽ cho JavaScript biết rằng bạn muốn khai báo một hàm Async thay vì hàm thông thường. Đó cũng là async key này sẽ cho phép bạn sử dụng await key bên trong hàm không đồng bộ đó. Nếu không, JavaScript sẽ ném ra SyntaxError. Thêm về điều này sau.
Hàm này hàm trả về promise.
Ví dụ :
async function helloWorld() { return "Hello World" } helloWorld().then( res => console.log(res) //in ra Hello World )
2. Await
Từ khóa Await được đặt trước 1 hàm làm cho hàm chờ một promise. Chỉ có thể sử dụng await bên trong một hàm Async.
Await - tạm dừng việc thực hiện các hàm async.
- Khi được đặt trước một Promise, nó sẽ đợi cho đến khi Promise kết thúc và trả về kết quả.
- Await chỉ làm việc với Promises, nó không hoạt động với callbacks.
- Await chỉ có thể được sử dụng bên trong các function async.
async function getJSONAsync() { // The await keyword saves us from having to write a .then() block. let json = await axios.get('https://tutorialzine.com/misc/files/example.json'); // The result of the GET request is available in the json variable. // We return it just like in a regular synchronous function. return json; }function findRandomImgPromise(tag) { const apiKey = 'a89c66e48519481ab448a3f8356e635c'; const endpoint = `https://api.giphy.com/v1/gifs/random?api_key=${apiKey}&tag=${tag}`; return fetch(endpoint) .then(rs => rs.json()) .then(data => data.data.fixed_width_small_url); } $('#request').click(async () => { const imgUrl = await findRandomImgPromise('cat'); $('#cat').attr('src', imgUrl); });
Như trong hình phía trên, hàm findRandomImgPromise là hàm bất đồng bộ, trả về một Promise. Với từ khoá await, ta có thể coi hàm này là đồng bộ, câu lệnh phía sau chỉ được chạy sau khi hàm này trả về kết quả.
Xử lý lỗi trong Async / Await
Một điều tuyệt vời khác về Async / Await là nó cho phép chúng ta bắt các lỗi không mong đợi bằng cách sử dụng try / catch. Chúng ta chỉ cần để các await call của chúng ta vào trong khối try/catch như sau:
Khi nói đến async / await và lỗi, có hai cách để xử lý chúng. Một cách là sử dụng catch()chức năng. Hàm async trả về một .Promise Khi lời hứa bị từ chối, nó là catch()chức năng cho phép bạn bắt và xử lý lỗi này. Điều này cũng hoạt động cho Async / await.
// Create async function async function myAsyncFunc() { // Create promise that rejects // and wait for its completion await new Promise((resolve, reject) => { reject('Promise rejected!') }) } // Invoke myAsyncFunc and catch the error myAsyncFunc() .catch(err => { console.log(`error: ${err}`) }) // 'error: Promise rejected!'
Một điều tuyệt vời khác về Async / Await là nó cho phép chúng ta bắt các lỗi không mong đợi bằng cách sử dụng try / catch. Chúng ta chỉ cần để các await call của chúng ta vào trong khối try/catch như sau:
/ Create async function async function myAsyncFunc() { // Create new promise that rejects const myPromise = new Promise((resolve, reject) => { reject('Promise rejected!') }) // Create try...catch statement try { // Await the promise to get rejected const message = await myPromise } catch(err) { // Catch any error and log it console.log(`error: ${err}`) } } // Invoke the myAsyncFunc() function myAsyncFunc() // 'error: Promise rejected!'
Tại sao nên dùng async/await?
Như mình đã nói, async/await có một số ưu điểm vượt trội so với promise:
- Code dễ đọc hơn rất rất nhiều, không cần phải then rồi catch gì cả, chỉ viết như code chạy tuần tự, sau đó dùng try/catch thông thường để bắt lỗi.
- Viết vòng lặp qua từng phần tử trở nên vô cùng đơn giản, chỉ việc await trong mỗi vòng lặp.
- Debug dễ hơn nhiều, vì mỗi lần dùng await được tính là một dòng code, do đó ta có thể đặt debugger để debug từng dòng như thường.
- Khi có lỗi, exception sẽ chỉ ra lỗi ở dòng số mấy chứ không chung chung là un-resolved promise.
- Với promise hoặc callback, việc kết hợp if/else hoặc retry với code asynchnous là một cực hình vì ta phải viết code lòng vòng, rắc rối. Với async/await, việc này vô cùng dễ dàng.
Bất cập của async/await
Tất nhiên, async/await cũng có một số bất cập mà các bạn cần phải lưu ý khi sử dụng:
- Không chạy được trên các trình duyệt cũ. Nếu dự án yêu cầu phải chạy trên các trình duyệt cũ, bạn sẽ phải dùng Babel để transpiler code ra ES5 để chạy.
- Khi ta await một promise bị reject, JavaScript sẽ throw một Exception. Do đó, nếu dùng async await mà quên try catch thì lâu lâu chúng ta sẽ bị… nuốt lỗi hoặc code ngừng chạy.
- async và await bắt buộc phải đi kèm với nhau! await chỉ dùng được trong hàm async, nếu không sẽ bị syntax error. Do đó, async/await sẽ lan dần ra toàn bộ các hàm trong code của bạn.
Kết luận
Cảm ơn các bạn đã theo dõi, chúc ngày lễ tốt lành.
Tham khảo : https://blog.alexdevero.com/javascript-async-await
All rights reserved
Tác giả : Cao Tiến ĐạtEmail : [email protected]ố điện thoại : 0975804410
Mọi ngôn ngữ lập trình đều không hoàn hảo, nó sẽ luôn có những ưu và nhược điểm riêng. Javascript - một trong những ngôn ngữ lập trình phổ biến nhất hiện nay, đã phải trải qua một khoảng thời gian dài khó khăn khi phải dựa vào callbacks để lập trình các đoạn code bất đồng bộ. Sau đó trong bản cập nhật ES7, JavaScript đã đưa ra một giải pháp mới được cộng đồng lập trình rất ủng hộ để giải quyết cái bài toàn bất đồng bộ chính là Async/Await.
Xử lí lỗi với Async/Await
Kết quả bình thường khi bạn sử dụng async/await là một kết quả đã được resolve. Nhưng khi promise bị reject và exception xảy ra thì phải làm gì? Chúng ta có thể dùng try…catch để giải quyết các lỗi này như các hàm bình thường khác.
Ví dụ:
Nếu một promise giải quyết bình thường, sau đó await promise trả về kết quả. Nhưng trong trường hợp từ chối, nó sẽ ném lỗi, giống như có một câu lệnh throw tại dòng đó.
async function f() { await Promise.reject(new Error("Whoops!")); }
Trong tình huống thực tế, lời hứa có thể mất một thời gian trước khi nó từ chối. Trong trường hợp đó sẽ có độ trễ trước khi await đưa ra lỗi.
Chúng ta có thể bắt lỗi đó bằng cách sử dụng try…catch, giống như cách thông thường throw:
async function f() { try { let response = await fetch('http://no-such-url'); } catch(err) { alert(err); // TypeError: failed to fetch } } f();
Async/Await là gì?
Trước đây, để làm việc với code bất đồng bộ, chúng ta sử dụng callback và promise, Async/Await là một cách mới để viết code bất đồng bộ, được Javascript giới thiệu từ bản cập nhật ES7. Nó được xây dựng trên Promise và tương thích với tất cả Promise dựa trên API. Trong đó:
Async được dùng để khai báo một hàm bất đồng bộ. Các hàm bất đồng bộ sẽ luôn trả về một giá trị. Việc sử dụng async chỉ đơn giản là ngụ ý rằng một lời hứa sẽ được trả lại và nếu một lời hứa không được trả lại, JavaScript sẽ tự động kết thúc nó.
Await được sử dụng để chờ một Promise. Nó chỉ có thể được sử dụng bên trong một khối Async. Từ khóa Await làm cho JavaScript đợi cho đến khi promise trả về kết quả. Cần lưu ý rằng nó chỉ làm cho khối chức năng không đồng bộ chờ đợi chứ không phải toàn bộ chương trình thực thi.
Async/Await và Promise
Nếu chúng ta xem qua, sẽ nghĩ rằng khi sử dụng Async/Await thì không cần phải sử dụng Promise nửa. Cũng không hẳn là vậy, vì bản chất khi ta sử dụng Async/Await chính là ta sử dụng gián tiếp Promise, khi async function return thì nó sẽ trả về 1 Promise, nếu ta hiểu bản chất sẽ biết cách áp dụng triệt để:
function returnPromise() { return new Promise(function(resolve,reject) { setTimeout(function() { resolve(5) }, 3000) }) } async function asyncFunction() { var result = await returnPromise() return result + 5 } var promise = asyncFunction() promise.then(function (value) { console.log(value) })
Ngoài ra: Chỉ có Promise có thể xử lý các trường hợp Callback ở các thư viện cũ, nên có lúc ta phải tự viết Promise để xử lý vấn đề cũ này.
Cách sử dụng Async/Await hiệu quả
Khi sử dụng Async/Await nó giúp chúng ta nhìn code tường minh hơn vì giúp code trở lại đồng bộ, tuy nhiên nếu quá lạm dụng thì sẽ làm chậm code.
Ví dụ:
function returnResultAfter3Seconds() { return new Promise(function(resolve,reject) { setTimeout(function() { resolve(5) }, 3000) }) } function returnResultAfter5Seconds() { return new Promise(function(resolve,reject) { setTimeout(function() { resolve(5) }, 5000) }) } async function asyncFunction() { var result1 = await returnResultAfter3Seconds() var result2 = await returnResultAfter5Seconds() return result1 + result2 } var promise = asyncFunction() promise.then(function (value) { console.log(value) })
Trong trường hợp này, ta có 2 hàm bất đồng bộ lần lượt mất 3 và 5 giây mới có kết quả, vì asyncFunction sử dụng await lần lượt thì mất đến 8 giây mới có thực hiện xong. Đây là vấn đề khi quá lạm dụng Async/Await khi không hiểu bản chất rõ Javascript, vì sức mạnh của ngôn ngữ Javascript chính là bất đồng bộ, khi ta viết như thế này sẽ không phát huy được tính năng của nó.
Để khắc phục tình trạng này, sử dụng Promise.all để cho 2 function chạy cùng 1 lúc, lúc đó thời gian giảm xuống còn 5 giây
function returnResultAfter3Seconds() { return new Promise(function(resolve,reject) { setTimeout(function() { resolve(5) }, 3000) }) } function returnResultAfter5Seconds() { return new Promise(function(resolve,reject) { setTimeout(function() { resolve(5) }, 5000) }) } async function asyncFunction() { var array = await Promise.all([returnResultAfter3Seconds(), returnResultAfter5Seconds()]) var result = 0 for (var i = 0; i < array.length - 1; i++) { result += array[i] } return result } var promise = asyncFunction() promise.then(function (value) { console.log(value) })
Kết luận
Async/await là 1 trong những tính năng mang tính cách mạng được thêm vào JavaScript trong vài năm gần đây. Nó giúp bạn nhận ra Promise còn thiếu sót như thế nào, cũng như cung cấp giải pháp thay thế.
Có thể bạn quan tâm:
- ES6 là gì? Những nổi bật và sự thay đổi tuyệt vời của ES6
- Mẹo với Javascript (ES6) và thủ thuật để làm cho code sạch hơn, ngắn hơn, và dễ đọc hơn ( Phần 2)
- 12 tips hay cho JavaScript
Xem thêm việc làm JavaScript Developer trên TopDev
TopDev via Hackernoon
Cảm ơn bạn!
async await trong JavaScript là gì? nó giúp ích gì cho chúng ta
Chào các bạn, lại là homiedev đây 😁. Tiếp tục với chủ đề bất đồng bộ (asynchronous) trong JavaScript, hôm nay mình xin giới thiệu đến các bạn từ khóa async/await trong JavaScript nhé. Cùng đọc bài viết thôi nào!
Async/Await là gì?
Async/Await là một tính năng ra đời từ ES7 nhằm giúp ta code bất đồng bộ nhìn trong đồng bộ hơn, giúp code dễ nhìn hơn và dễ sử dụng. Trong đó:
- Async function là một khái niệm định nghĩa cho hàm bất đồng bộ. Hàm bất đồng bộ này sẽ thực hiện tách rời so với phần code còn lại của Event Loop, và trả về một Promise. Cú pháp và cấu trúc của Async function làm nhìn giống chuẩn các hàm đồng bộ.
- Await là một cú pháp giúp tạm dừng (block) code để đợi lấy kết quả từ một Promise (Await không hoạt động với callback), và Await chỉ sử dụng được khi nằm trong Async function.
Ví dụ: Ta sẽ viết 1 function dùng Async/Await để xử lý 1 Promise
- Khai báo function returnPromise khi gọi sẽ return 1 promise, sau 3 giây thì promise sẽ resolve kết quả.
- Khai báo function asyncFunction dùng tính năng async/await, khi gọi function returnPromise sẽ dùng await để đợi kết quả.
Ta sẽ xem kết quả của nó:
Như vậy:
- Khi gọi asyncFunction đầu tiên thì chương trình sẽ log ‘calling’, nhưng khi chương trình await nên chương trình thực hiện log ‘kteam’ tiếp theo.
- Sau 3 giây thì returnPromise có kết quả, lúc đó asyncFunction thực hiện tiếp phần code còn lại.
function returnPromise() { return new Promise(function(resolve,reject) { setTimeout(function() { resolve('finished') }, 3000) }) } async function asyncFunction() { console.log('calling') var result = await returnPromise() console.log(result) } asyncFunction() console.log('kteam')
Javascript async/await
Chúng ta sử dụng từ khóa
async
cho một hàm để thể hiện rằng hàm này là một hàm bất đồng bộ. Hàm
async
trả về một promise.
Cú pháp của hàm
async
là:
async function name(parameter1, parameter2, ...paramaterN) { // ... }
Trong đó:
- name - tên của chức năng
- parameters - tham số được truyền cho hàm
Ví dụ về async function:
async function f() { console.log('Async function.'); return Promise.resolve('homiedev.com'); } f();
Kết quả chúng ta nhận được:
Async function. Promise {
: 'homiedev.com'}
Ở ví dụ trên, từ khóa
async
được sử dụng trước function để biểu thị rằng hàm này là bất đồng bộ (vì bên trong chúng ta xử lý bất đồng bộ).
Vì hàm này return một promise, nên có thể sử dụng method
then()
như sau:
async function f() { console.log('Async function.'); return Promise.resolve('homiedev.com'); } f().then(function(result) { console.log(result) });
Kết quả là:
Async function. homiedev.com
Trong ví dụ trên, khi hàm
f()
resolved, method
then()
được thực thi.
JavaScript await
Từ khóa
await
được sử dụng bên trong hàm async để chờ một xử lý bất đồng bộ.
Cú pháp để sử dụng
await
là:
let result = await promise;
Khi sử dụng từ khóa
await
, nó sẽ tạm dừng async function cho đến khi promise return về giá trị kết quả (resolve hoặc reject).
Ví dụ:
let promise = new Promise(function (resolve, reject) { // chờ sau 3 giây thì gọi resolve setTimeout(function () { resolve('Promise resolved') }, 3000); }); // async function async function asyncFunc() { // chờ cho đến khi promise resolve let result = await promise; console.log(result); console.log('homiedev.com'); } // gọi async function asyncFunc();
Kết quả ví dụ trên:
Promise resolved homiedev.com
Ở ví dụ trên, object Promise được tạo và nó sẽ được resolve sau 3 giây. Ở đây, hàm
asyncFunc()
là một async function.
Trong hàm async, chúng ta sử dụng từ khóa
await
để đợi promise hoàn thành (resolve hoặc reject). Bạn có thể hiểu là quá trình này giống khi chúng ta đứng đợi ở trạm xe bus, chúng ta sẽ đứng chờ 5 - 10 phút và khi xe bus đến chúng ta sẽ lên xe và đi tới một địa điểm khác. Quá trình này dừng khi chúng ta đến địa điểm cần đến ^^.
Thêm nữa, dòng chữ
homiedev.com
chỉ được hiển thị sau khi giá trị promise được trả cho biến result ở ví dụ trên.
Nếu ta không sử dụng
await
, dòng chữ
homiedev.com
sẽ hiển thị trước khi Promise resolve.
Chúng ta chỉ có thể sử dụng
await
bên trong
async function
.
Chúng ta cùng xem tiếp một ví dụ sử dụng nhiều promise nhé!
Ví dụ:
let promise1; let promise2; let promise3; async function asyncFunc() { let result1 = await promise1; let result2 = await promise2; let result3 = await promise3; console.log(result1); console.log(result2); console.log(result3); console.log('homiedev.com'); }
Trong đoạn code trên,
await
sẽ chờ từng promise hoàn thành. Và
homiedev.com
sẽ được in ra cuối cùng 😉.
Xử lý lỗi
Trong khi sử dụng async function, chúng ta xử lý code bên trong theo kiểu đồng bộ. Nếu có lỗi trong quá trình xử lý thì chúng ta có thể sử dụng method
catch()
để bắt lỗi.
Ví dụ:
asyncFunc().catch( // Xử lý lỗi tại đây )
Chúng ta còn một cách khác đó là xử lý lỗi sử dụng try ... catch.
Ví dụ:
let promise = new Promise(function (resolve, reject) { setTimeout(function () { reject('Lỗi mất rồi !😢'); }, 3000); }); // async function async function asyncFunc() { try { // promise trả về lỗi ngay sau đó sẽ xử lý lỗi ở catch let result = await promise; console.log(result); } catch(error) { // xử lý lỗi tại đây console.log(error); } } // gọi async function asyncFunc(); // Lỗi mất rồi !😢
Trong ví dụ trên, chúng ta đã sử dụng try ... catch để xử lý các lỗi. Nếu chương trình chạy thành công, nó sẽ chuyển đến khối
try
. Và chương trình throw ra một lỗi, nó sẽ chuyển đến khối
catch
. Ở ví dụ trên promise đã reject nên chương trình sẽ chuyển sang
catch
.
async Function giúp được gì?
- Giúp cho code dễ đọc hơn là sử dụng callback hay promise.
- Xử lý lỗi đơn giản hơn.
- Debug dễ dàng hơn.
Từ khóa
async / await
này đã được giới thiệu trong bản JavaScript (ES8). Một số trình duyệt cũ hơn có thể không hỗ trợ việc sử dụng
async / await
. Các bạn có thể tìm hiểu tại đây.
Async/await Trong JavaScript
Async / await
được giới thiệu bởi ES7 là một cải tiến từ promise mang đến điều tuyệt vời trong
Asynchronous programming
với JavaScript. Nó cung cấp cho các developer js viết mã đồng bộ (synchronous) trên những chức năng không đồng bộ (
asynchonous
), mà không làm gián đoạn code của chính mình. Tuy nhiên không hẳn những developer nào cũng có thể sử dụng chúng một cách hiệu quả và sâu hơn nữa là hiểu cốt lõi của việc sử dụng chúng. Trong bài viết này chúng ta sẽ cùng nhau khám phá về của
async / await
qua các ví dụ.
Async / Await là một tính năng của JavaScript giúp chúng ta làm việc với các hàm bất đồng bộ theo cách thú vị hơn và dễ hiểu hơn. Nó được xây dựng trên
promise
và tương thích với tất cả các
promise
dựa trên API. Đầu tiên chúng ta hãy bắt đầu với
async
trước.
Async/await 101
Với những ai chưa hề nghe qua về Async/await thì đây là những giới thiệu ngắn gọn:
- Async/await là cách mới để viết code bất đồng bộ. Các phương pháp làm việc với code bất đồng bộ trước đây là sử dụng callback và promise.
- Async/await là khái niệm được xây dựng ở tầng trên promise. Do đó nó không thể sử dụng với callback thuần.
- Async/await cũng giống như promise, là non-blocking.
- Async/await làm cho code bất đồng bộ nhìn và chạy gần giống như code đồng bộ.
Keywords searched by users: async await trong javascript
Categories: Có được 10 Async Await Trong Javascript
See more here: kientrucannam.vn
See more: https://kientrucannam.vn/vn/