Async/await

Async/await

Từ phiên bản ES2017, Javascript đã thêm hai từ khóa asyncawait. Đây là các cú pháp thay thế cho cú pháp cũ là constructor Promise(), hàm then(), catch(), còn bản chất Promise vẫn giữ nguyên.

Hàm async

Từ khóa async đặt trước hàm để chuyển hàm đó từ hàm đồng bộ sang thành hàm bất đồng bộ (async function). Hàm bất đồng bộ khi thực thi sẽ trả về một Promise.

Ví dụ về hàm async:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

async

function

hello

()

{

return

"Hello asyc"

}

// hàm thông thường

let

hello1

=

async

function

()

{

return

"Hello express"

};

// biểu thức hàm

let

hello2

=

async

()

=>

"Hello arrow"

;

// hàm mũi tên

class

Person

{

async

greeting

()

{

// phương thức async

return

"Hello method"

;

};

}

// sử dụng hàm bất đồng bộ

hello

().

then

((

message

)

=>

console

.

log

(

message

));

// Hello asyc

hello1

().

then

((

message

)

=>

console

.

log

(

message

));

// Hello express

hello2

().

then

((

message

)

=>

console

.

log

(

message

));

// Hello arrow

// Hello method

new

Person

().

greeting

().

then

(

message

=>

console

.

log

(

message

));

Trong ví dụ trên hàm hello() ở trên tương đương với:

1

2

3

function

hello

()

{

return

Promise

.

resolve

(

"Hello asyc"

);

}

Từ khóa await

Từ khóa await đặt trước biểu thức Promise để lấy giá trị trả về. Từ khóa await phải đặt trong hàm async. Khi gặp câu lệnh với từ khóa await, Promise phải thực thi xong mới chạy câu lệnh tiếp theo. Tức là các câu lênh await sẽ chuyển thực thi Promise bất đồng bộ thành chạy tuần tự.

Ví dụ đơn giản sử dụng await:

1

2

3

4

5

6

7

async

function

hello

()

{

// đặt trước string sẽ chuyển string thành Promise

let

message

=

await

"Hello asyc"

;

return

message

;

};

hello

().

then

((

message

)

=>

console

.

log

(

message

));

// Hello asyc

Ví dụ khác sử dụng await:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

// promise1 và promise2 là hàm trả về Promise

const

promise1

=

()

=>

new

Promise

((

resolve

,

reject

)

=>

{

setTimeout

(

resolve

,

500

,

123

);

});

const

promise2

=

()

=>

new

Promise

((

resolve

,

reject

)

=>

{

setTimeout

(

resolve

,

100

,

456

);

});

async

function

getNumber

()

{

// promise1 chạy xong đến promise2 sẽ chạy

// mất thời gian tổng cộng 600ms

let

firstNumber

=

await

promise1

();

let

secondNumber

=

await

promise2

();

return

firstNumber

+

secondNumber

;

};

getNumber

().

then

((

number

)

=>

console

.

log

(

number

));

// 579

Hàm setNumber() ở ví dụ trên có thể viết lại như sau:

1

2

3

4

5

6

7

function

getNumber

()

{

let

firstNumber

,

secondNumber

;

return

Promise

.

resolve

()

.

then

(()

=>

promise1

().

then

(

number

=>

firstNumber

=

number

))

.

then

(()

=>

promise2

().

then

(

number

=>

secondNumber

=

number

))

.

then

(()

=>

firstNumber

+

secondNumber

);

};

Chúng ta thấy rằng viết Promise theo kiểu async/await như ví dụ trước là dễ đọc và dễ hiểu tương tự cú pháp thông thường.

Quản lý lỗi với try-catch

Chúng ta sử dụng try-catch thay cho hàm catch() để quản lý lỗi với Promise sử dụng async/await.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

const

promise1

=

()

=>

new

Promise

((

resolve

,

reject

)

=>

{

setTimeout

(

reject

,

500

,

123

);

});

const

promise2

=

()

=>

new

Promise

((

resolve

,

reject

)

=>

{

setTimeout

(

resolve

,

100

,

456

);

});

async

function

getNumber

()

{

try

{

let

firstNumber

=

await

promise1

();

let

secondNumber

=

await

promise2

();

return

firstNumber

+

secondNumber

;

}

catch

(

error

)

{

console

.

error

(

'Lỗi trong promise '

+

error

.

toString

());

// 123

}

};

getNumber

();

Chạy promise đồng thời với Promise.all()

Toán tử await sẽ chạy các promise tuần tự, để chạy đồng thời hãy sử dụng hàm Promise.all

Ví dụ sau chạy đồng thời hai promise nên thời gian sẽ chạy ít hơn ví dụ trước 100ms.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

const

promise1

=

()

=>

new

Promise

((

resolve

,

reject

)

=>

{

setTimeout

(

resolve

,

500

,

123

);

});

const

promise2

=

()

=>

new

Promise

((

resolve

,

reject

)

=>

{

setTimeout

(

resolve

,

100

,

456

);

});

async

function

getNumber

()

{

// chạy song song nên thời gian chạy là khoảng 500ms

return

Promise

.

all

([

promise1

(),

promise2

()])

.

then

(([

firstNumber

,

secondNumber

])

=>

firstNumber

+

secondNumber

)

};

getNumber

().

then

((

number

)

=>

console

.

log

(

number

));

// 579