• About
  • Advertise
  • Privacy & Policy
  • Contact
NQ NEWS
  • Kiến thức tổng hợp
    • Development
    • Deep Learning
    • Cloud Computing
    • Kiến thức bảo mật
    • Tin học văn phòng
  • Thủ thuật
    • Phần Mềm
    • Sửa lỗi máy tính
    • Bảo mật máy tính
    • Tăng tốc máy tính
    • Thủ thuật Wifi
  • Quản trị hệ thống
    • Giải pháp bảo mật
    • Mail Server
    • Mạng LAN – WAN
    • Máy chủ
    • Windows Server 2012
  • Tin tức
No Result
View All Result
  • Kiến thức tổng hợp
    • Development
    • Deep Learning
    • Cloud Computing
    • Kiến thức bảo mật
    • Tin học văn phòng
  • Thủ thuật
    • Phần Mềm
    • Sửa lỗi máy tính
    • Bảo mật máy tính
    • Tăng tốc máy tính
    • Thủ thuật Wifi
  • Quản trị hệ thống
    • Giải pháp bảo mật
    • Mail Server
    • Mạng LAN – WAN
    • Máy chủ
    • Windows Server 2012
  • Tin tức
No Result
View All Result
NQ NEWS
No Result
View All Result
Home Kiến thức tổng hợp

Cơ bản về Async Await trong Javascript

@admiz by @admiz
04/05/2021
in Kiến thức tổng hợp
0
Cơ Bản Về Async Await Trong Javascript 60902d17208d7.png

Khi bắt đầu lập trình với Nodejs, vì Javascript (JS) là bất đồng bộ (asynchoronous) nên mình gặp khó khăn trong việc tổ chức code giống như trong lập trình đồng bộ (synchoronous). Việc cho các đoạn code vào trong các callback khiến mình cảm thấy code trở lên khó đọc theo luồng như trong PHP hay Ruby, nên mình đã tìm hiểu và sử dụng cú pháp async await theo chuẩn ES6 của JS. Sử dụng các cú pháp mới này giúp cho code của mình có thể tổ chức rõ ràng hơn.

Khi sử dụng cú pháp async await thì bạn phải nắm được luồng chạy trong các hàm này và cái gì được trả về trong các hàm này. Sau đây mình xin trình bày trình tự chạy các câu lệnh khi có async await trong Nodejs.

Xét ví dụ căn bản khi không có async await sau đây

execute()

function execute() {

findResult()

console.log(“end of execute”)

function findResult() {

for(var i = 0; i

var j = 100

console.log(‘before findResult’)

db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ ,

function(err, result){

console.log(‘inner findResult callback’)

)

console.log(‘after findResult’)

Đoạn code trên có findOne() là hàm chạy async nên chẳng có gì bàn cãi khi thứ tự in ra sẽ là:

before findResult

after findResult

end of execute

inner findResult callback

Lại xét ví dụ căn bản khi có hàm async await sau đây.

execute()

function execute() {

findResult()

console.log(“end of execute”)

async function findResult() {

for(var i = 0; i

var j = 100

console.log(‘before findResult’)

var result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ ) // don’t write callback here

// process with result here

console.log(‘after findResult’)

Người ta tạo ra async await là để tránh các hàm callback nên đừng viết await và callback cùng nhau.

Bạn dự đoán đoạn code trên sẽ in ra thứ tự thế nào?

Thứ tự sẽ như sau:

before findResult

end of execute

after findResult

Để trả lời câu hỏi trên thì cần nhớ một số chú ý 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)

• Thứ tự thực hiện các câu lệnh trong js nói chung hay nodejs nói riêng đều là chạy từ trên xuống dưới (nghĩa là chạy sync chứ không phải async), trừ những hàm liên quan tới I/O thì mới được chạy async (Tham khảo thêm ở bài viết event loop trong js )

• Khi gặp await, nó sẽ convert hàm đó thành promise với callback là tất cả những phần code phía sau await đó. Bản chất await là một promise, phần code nằm sau await thực chất là code nằm trong callback của hàm await đó. Ví dụ 2 đoạn mã dưới đây là tương đương nhau:

async function test() {

var result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(‘after findResult: ‘, result)

… more code here …

//

//tương đương với

function test() {

db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ , function(result){

console.log(‘after findResult: ‘, result)

… more code here …

)

Nếu nắm được ví dụ trên kia rồi thì những đoạn code phía sau đây bạn sẽ biết thứ tự và kết quả được in ra như thế nào:

Ví dụ 1:

execute()

function execute() {

var result = findResult()

console.log(result)

async function findResult() {

for(var i = 0; i

var j = 100

console.log(‘before findResult’)

await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(‘after findResult’)

Thứ tự in ra là:

before findResult

Promise {

after findResult

Để ý thấy hàm findResult dù ko return j nhưng result vẫn in ra là một Promise vì hàm có khai báo async ở phía trước luôn trả về một Promise(giải thích ở phía sau).

Thế để lấy kết quả thực từ câu lệnh findOne() của VD1 ở hàm execute() thì chúng ta cần phải làm gì? Vì findResult() trả về một Promise nên ta chỉ cần gọi hàm then() ở nơi được trả về là được, xét ví dụ 2 sau đây:

Ví dụ 2:

execute()

function execute() {

findResult().then(function(result){ // call then() here to capture result in async function

console.log(result)

)

console.log(‘end of execute’)

async function findResult() {

for(var i = 0; i

var j = 100

console.log(‘before findResult’)

var result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(‘after findResult’)

return result

Kết quả in ra sẽ là:

before findResult

end of execute

after findResult

{ _id: 59e8d6930c9c77b21c42d704,

…..

Hàm async luôn trả về một promise

Gọi hàm có từ khóa async phía trước luôn trả về một promise, dù trong hàm đó có await hay không.

Ví dụ 1:

function test() {

var promise = returnTen()

console.log(promise)

async function returnTen() {

return 10

test() // Promise { 10

Ví dụ này promise trả về có kết quả là 10 luôn.

Ví dụ 2: 

function test() {

var promise = returnTen()

console.log(promise)

async function returnTen() {

return await 10

test() // Promise {

Ví dụ này promise trả về chưa có kết quả luôn.

Khi await nằm trong loop

Chú ý là nếu await nằm trong loop thì sẽ khác biệt một chút, xét đoạn code sau:

for(var i = 0; i

console.log(‘before async: ‘, i)

var result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(‘after async: ‘, i)

Nhiều người có lẽ sẽ nghĩ đoạn code trên tương đương với:

for(var i = 0; i

console.log(‘before async: ‘, i)

var result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(‘after async: ‘, i)

//before async: 0

//before async: 1

//before async: 2

//after async: 3

//after async: 3

//after async: 3

Nhưng không phải, mỗi khi gặp await thì phải đợi kết quả trả về mới chạy tiếp tới i tiếp theo, đoạn code tương đương sẽ là như sau:

var i = 0

console.log(‘before async: ‘, i) // before async: 0

db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ , function(){

console.log(‘after async: ‘, i) // after async: 0

i

console.log(‘before async: ‘, i) // before async: 1

db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ , function(){

console.log(‘after async: ‘, i) // after async: 1

i

console.log(‘before async: ‘, i) // before async: 2

db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ , function(){

console.log(‘after async: ‘, i) // after async: 2

i

)

)

)

Ví dụ kiểm tra:

execute()

function execute() {

findResult().then(function(result){ // call then() here to capture result in async function

console.log(result)

)

console.log(‘end of execute’)

async function findResult() {

for(var i = 0; i

console.log(‘before findResult: ‘, i)

result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(i, result)

return i

Kết quả in ra sẽ là:

before findResult: 0

end of execute

0 { _id: 59f972567909e65c67a28b1b,

………………

before findResult: 1

1 { _id: …..,

………………

before findResult: 2

2 { _id: …..,

………………

before findResult: 3

3 { _id: …..,

………………

before findResult: 4

4 { _id: …..,

………………

5 //

Xét ví dụ khó hơn khi có 2 hàm async lồng nhau

Ví dụ 1: Hàm thứ 2 là hàm bình thường nhưng có khối async ở phía trong.

execute()

function execute() {

findResult().then(function(result){

console.log(‘result 1:’, result)

)

console.log(‘end of execute’)

async function findResult() {

for(var i = 0; i

var j = 100

fA().then(function(result) {

console.log(‘result 2: ‘, result)

)

console.log(‘before findResult’)

var result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(‘after findResult’)

return result

function fA() {

for(var i = 0; i

var j = 100

console.log(‘before fA’)

var result = db.collection(‘hospitals’).findOne({name: ‘都志見病院’ )

console.log(‘after fA’)

return result

Thứ tự in ra sẽ là:

before fA

after fA

before findResult

end of execute

result 2: {…

after findResult

result 1: {…

Giải thích:

• Trình tự in ra từ đầu cho tới “end of execute” như dự đoán vì code chạy đúng như trình tự synchronous (đồng bộ, hay từ trên xuống dưới)

• Vì sao “after findResult” lại được in ra trước “result 1: {… ” ???:

Vì khi gọi await ở trong hàm f*indResult* thì console.log(‘after findResult’) đã bị đặt vào callback của hàm await đó rồi mới tới return result cho callback của result1 được in ra.

• Vì sao “result 2: {… ” được in ra trước “result 1: {… ” ???:

2 lời gọi fA() trong findResult() và findResult() trong execute() là 2 hàm async không phụ thuộc vào nhau nên hàm nào có kết quả trả về trước sẽ được thực thi trước.

Ở trên thì câu lệnh async ở dòng 36 có kết quả trả về nhanh hơn kết quả trả về ở câu lệnh 22.

Nếu không tin bạn có thể tùy biến cho câu lệnh ở dòng 36 có thời gian thực thi mất 10 giây, lúc này “result2: {… ” sẽ được in ra sau “result 1: {… “

Ví dụ 2: Hàm thứ 2 là hàm async.

execute()

function execute() {

findResult().then(function(result){

console.log(‘result 1:’, result)

)

console.log(‘end of execute’)

async function findResult() {

for(var i = 0; i

var j = 100

fA().then(function(result) {

console.log(‘result 2: ‘, result)

)

console.log(‘before findResult’)

var result = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(‘after findResult’)

return result

async function fA() {

for(var i = 0; i

var j = 100

console.log(‘before fA’)

result = await db.collection(‘hospitals’).findOne({name: ‘都志見病院’ )

console.log(‘after fA’)

return result

Thứ tự in ra sẽ là:

before fA

before findResult

end of execute

after fA

result 2: {…

after findResult

result 1: {…

Cái này được giải thích giống ví dụ trên, và cũng giống như ví dụ trên result 2 được in ra trước result 1 vì hàm async của nó được trả về giá trị sớm hơn.

Một số chú ý khi sử dụng async/await(promise) trong Javascript

• Chú ý khi sử dụng await trong vòng lặp như đã nói phía trên.

• Khi gặp await thì những đoạn code phía sau có kết quả trả về mới thực hiện được nên nếu phần code phía sau không phụ thuộc vào await thì bạn nên xử lý như sau:

Xét ví dụ sau:

async function test() {

var result1 = await db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

console.log(result1)

var result2 = await db.collection(‘hospitals’).findOne({name: ‘abcxyz’ )

console.log(result2)

test()

Đoạn code trên result1 có kết quả trả về thì hàm lấy result2 mới được chạy. Nhưng điều bạn muốn là cả 2 hàm lấy result1 và result2 phải chạy song song, bạn cần chuyển thành như sau:

async function test() {

var promise1 = db.collection(‘hospitals’).findOne({name: ‘医療法人神甲会隈病院’ )

var promise2 = db.collection(‘hospitals’).findOne({name: ‘abcxyz’ )

var result1 = await promise1

console.log(result1)

var result2 = await promise2

console.log(result2)

test()

Nhìn 2 đoạn code có vẻ giống nhau nhưng khác nhau một trời một vực đấy. Bạn nên đọc bài cơ chế hoạt động của Javascript để nắm được trình tự Javascript chạy các câu lệnh như thế nào.

Post Views: 130
Previous Post

Docker: Chưa biết gì đến biết dùng (Phần 1)

Next Post

Con trỏ This trong Javascript. Những kiến thức cơ bản cần biết

Related Posts

Sửa Nhanh Lỗi Laptop Windows 10 Sạc Pin Không Vào 60951215e059b.png
Phần cứng

Sửa nhanh lỗi laptop Windows 10 sạc pin không vào

11/05/2022
Làm Thế Nào để Xóa Một Phân Vùng Trên ổ đĩa Cứng Windows? 60951232be65c.png
Phần cứng

Làm thế nào để xóa một phân vùng trên ổ đĩa cứng Windows?

11/05/2022
Test Pin Laptop, Cách Kiểm Tra Pin Laptop đang ở Mức Nào Mà Không Cần Cài Phần Mềm 6095123831651.png
Phần cứng

Test pin laptop, cách kiểm tra pin laptop đang ở mức nào mà không cần cài phần mềm

11/05/2022
Hướng Dẫn Xử Lý Khi Key Bàn Phím Laptop Bị Hỏng 6095121ca32df.png
Phần cứng

Hướng dẫn xử lý khi key bàn phím laptop bị hỏng

11/05/2022
Nên Dùng Súng Loại Nào Trong Chiến Dịch Huyền Thoại? 6094aaf17f1da.png
Phần Mềm

Nên dùng súng loại nào trong Chiến Dịch Huyền Thoại?

07/05/2022
Hướng Dẫn Cài đặt Wtfast để Giảm Ping Khi Chơi Game Online, Khi đứt Cáp 6094aae16ee4b.png
Phần Mềm

Hướng dẫn cài đặt WTFast để giảm ping khi chơi game online, khi đứt cáp

07/05/2022
Next Post
Con Trỏ This Trong Javascript. Những Kiến Thức Cơ Bản Cần Biết 60902d1b9cd00.jpeg

Con trỏ This trong Javascript. Những kiến thức cơ bản cần biết

Bài mới nhất

Website Defacement Là Gì Và Cách Khắc Phục Hiệu Quả Cho Website 612d235622440.png

Website Defacement là gì và cách khắc phục hiệu quả cho website

12/05/2025
8 Cách Quản Lý Data Khách Hàng Hiệu Quả Cho Doanh Nghiệp 612d234c2b5ad.jpeg

8 cách quản lý data khách hàng hiệu quả cho doanh nghiệp

12/05/2025
Địa Chỉ Email Là Gì Và Cách để Tạo Lập địa Chỉ Mail Chuyên Nghiệp 612d23693d14c.jpeg

Địa chỉ email là gì và cách để tạo lập địa chỉ mail chuyên nghiệp

11/05/2025
Tự động Hóa Bán Hàng: Cách ứng Dụng Crm Vào Bán Hàng Và Marketing 612d0eb0e2b27.jpeg

Tự động hóa bán hàng: Cách ứng dụng CRM vào bán hàng và Marketing

11/05/2025
Remarketing Là Gì, Lợi ích Và Các Hiệu Quả Mà Hoạt động Này Mang Lại 612d0eb8a4bc4.jpeg

Remarketing là gì, lợi ích và các hiệu quả mà hoạt động này mang lại

10/05/2025

Danh mục

  • Android
  • Bảo mật máy tính
  • Bảo mật, Antivirus
  • Chuyện công nghệ
  • Deep Learning
  • Development
  • Dịch vụ công trực tuyến
  • Dịch vụ nhà mạng
  • Giải pháp bảo mật
  • Hệ thống
  • Hệ thống
  • iPhone
  • Kiến thức bảo mật
  • Kiến thức cơ bản phổ thông
  • Kiến thức Marketing căn bản
  • Kiến thức tổng hợp
  • Lập trình
  • Linux
  • Linux OS
  • macOS
  • Mail Server
  • Mạng LAN – WAN
  • Máy ảo
  • Máy chủ
  • ms excel
  • ms-powerpoint
  • Nền tảng điện toán đám mây
  • Phần cứng
  • Phần Mềm
  • Quản trị hệ thống
  • Raspberry Pi
  • Sửa lỗi máy tính
  • Tăng tốc máy tính
  • Thủ thuật
  • Thủ thuật SEO
  • Thủ thuật Wifi
  • Tiện ích hệ thống
  • Tin học văn phòng
  • Tin tức
  • Uncategorized
  • Ứng dụng
  • Website
  • Windows Server 2012

Thẻ

#app #chatbot #chatbot tự động #CRM #Kiến thức cơ bản #Techblog #Thiết kế website Android apple CPU Email Marketing Google Google Drive hacker HTML hàm python hàm python có sẵn hình nền hình nền máy tính học css học python học SQL ios iphone iphone 12 iPhone X macos Microsoft mssql MS SQL Server ngôn ngữ lập trình python Raspberry Pi Samsung smartphone SQL SQL Server tham số trong C thủ thuật windows 10 tài liệu python windows windows 10 YouTube điện thoại thông minh ứng dụng
  • About
  • Advertise
  • Privacy & Policy
  • Contact

© 2022 Pha Le Solution

No Result
View All Result
  • Home

© 2022 Pha Le Solution