await
async/await là cú pháp giúp viết xử lý bất đồng bộ sử dụng Promise một cách đơn giản hơn.
Với cú pháp này, bạn có thể viết xử lý bất đồng bộ giống như xử lý đồng bộ hơn.
async/await thường được sử dụng cùng nhau, nhưng trong trang này chúng ta sẽ tập trung vào await.
await
await chờ cho đến khi giá trị của Promise được resolve và trả về giá trị đã resolve.
Lưu ý rằng về cơ bản await chỉ có thể sử dụng bên trong function async.
ts// Trả về giá trị sau 1 giâyfunctionrequest ():Promise <string> {return newPromise ((resolve ) => {setTimeout (() => {resolve ("hello");}, 1000);});}// Không thể viết như thế này// const result = await request();// console.log(result);async functionmain () {constresult = awaitrequest ();console .log (result );// @log: "hello"}main ();
ts// Trả về giá trị sau 1 giâyfunctionrequest ():Promise <string> {return newPromise ((resolve ) => {setTimeout (() => {resolve ("hello");}, 1000);});}// Không thể viết như thế này// const result = await request();// console.log(result);async functionmain () {constresult = awaitrequest ();console .log (result );// @log: "hello"}main ();
Trong ví dụ này, tại dòng await request(), chương trình sẽ chờ 1 giây cho đến khi request() resolve Promise, sau đó hiển thị "hello" ra console.
Viết lại bằng async/await
Cuối cùng, hãy viết lại code gọi 3 API bằng cách sử dụng async/await.
Như vậy, bằng cách sử dụng async/await, bạn có thể viết xử lý bất đồng bộ một cách gọn gàng giống như xử lý đồng bộ.
ts// Xử lý gọi API bất đồng bộ để lấy giá trịfunctionrequest1 ():Promise <number> {return newPromise ((resolve ) => {setTimeout (() => {resolve (1);}, 1000);});}// Xử lý nhận giá trị và gọi API khác để lấy giá trịfunctionrequest2 (result1 : number):Promise <number> {return newPromise ((resolve ) => {setTimeout (() => {resolve (result1 + 1);}, 1000);});}// Xử lý nhận giá trị và gọi API khác để lấy giá trịfunctionrequest3 (result2 : number):Promise <number> {return newPromise ((resolve ) => {setTimeout (() => {resolve (result2 + 2);}, 1000);});}async functionmain () {constresult1 = awaitrequest1 ();constresult2 = awaitrequest2 (result1 );constresult3 = awaitrequest3 (result2 );console .log (result3 );// @log: 4}main ();
ts// Xử lý gọi API bất đồng bộ để lấy giá trịfunctionrequest1 ():Promise <number> {return newPromise ((resolve ) => {setTimeout (() => {resolve (1);}, 1000);});}// Xử lý nhận giá trị và gọi API khác để lấy giá trịfunctionrequest2 (result1 : number):Promise <number> {return newPromise ((resolve ) => {setTimeout (() => {resolve (result1 + 1);}, 1000);});}// Xử lý nhận giá trị và gọi API khác để lấy giá trịfunctionrequest3 (result2 : number):Promise <number> {return newPromise ((resolve ) => {setTimeout (() => {resolve (result2 + 2);}, 1000);});}async functionmain () {constresult1 = awaitrequest1 ();constresult2 = awaitrequest2 (result1 );constresult3 = awaitrequest3 (result2 );console .log (result3 );// @log: 4}main ();
await trực tiếp một Promise
Bạn cũng có thể await một Promise trực tiếp mà không cần tạo function.
tsasync functionmain () {// Trả về giá trị sau 1 giâyawait newPromise ((resolve ) => {setTimeout (() =>resolve , 1000);});}
tsasync functionmain () {// Trả về giá trị sau 1 giâyawait newPromise ((resolve ) => {setTimeout (() =>resolve , 1000);});}
await một function async
Bạn cũng có thể await một function async.
tsasync functionrequest ():Promise <string> {return "hello";}async functionmain () {constresult = awaitrequest ();console .log (result );// @log: "hello"}
tsasync functionrequest ():Promise <string> {return "hello";}async functionmain () {constresult = awaitrequest ();console .log (result );// @log: "hello"}
Type annotation khi await
Type annotation của giá trị trả về khi await một Promise hoặc function async là T trong Promise<T>.
tsasync functionrequest ():Promise <string> {return "hello";}async functionmain () {constresult : string = awaitrequest ();// Kiểu là stringconsole .log (result );// @log: "hello"}
tsasync functionrequest ():Promise <string> {return "hello";}async functionmain () {constresult : string = awaitrequest ();// Kiểu là stringconsole .log (result );// @log: "hello"}
Viết lại then-catch bằng try-catch
Bạn có thể viết lại then và catch của Promise bằng try-catch. Function main2 dưới đây là phiên bản viết lại của function main1 bằng try-catch.
tsasync functionrequest ():Promise <string> {return "hello";}functionmain1 () {request ().then ((result : string) => {console .log (result );// @log: "hello"}).catch ((error : unknown) => {console .log (error );});}async functionmain2 () {try {constresult : string = awaitrequest ();console .log (result );// @log: "hello"} catch (error : unknown) {console .log (error );}}
tsasync functionrequest ():Promise <string> {return "hello";}functionmain1 () {request ().then ((result : string) => {console .log (result );// @log: "hello"}).catch ((error : unknown) => {console .log (error );});}async functionmain2 () {try {constresult : string = awaitrequest ();console .log (result );// @log: "hello"} catch (error : unknown) {console .log (error );}}
Khi return một Promise bị reject
await trước khi return
Khi await một Promise bị reject trước khi return, exception sẽ được throw trong function đó.
tsasync functionrequest ():Promise <unknown> {throw newError ("error");}async functionmain ():Promise <unknown> {try {// Bằng cách sử dụng return await, exception có thể được bắt trong catchreturn awaitrequest ();} catch {console .log ("error");// @log: error} finally {console .log ("finally");// @log: finally}}main ().then (() => {console .log ("then");// @log: then}).catch (() => {console .log ("catch");});
tsasync functionrequest ():Promise <unknown> {throw newError ("error");}async functionmain ():Promise <unknown> {try {// Bằng cách sử dụng return await, exception có thể được bắt trong catchreturn awaitrequest ();} catch {console .log ("error");// @log: error} finally {console .log ("finally");// @log: finally}}main ().then (() => {console .log ("then");// @log: then}).catch (() => {console .log ("catch");});
Trong ví dụ như thế này, các giá trị hiển thị sẽ là error, finally, và then.
Không await trước khi return (chỉ return)
Nếu return một Promise bị reject trực tiếp mà không await, nó sẽ được trả về cho caller trong trạng thái bị reject.
tsfunctionrequest ():Promise <unknown> {throw newError ("error");}// try -> finally -> return -> catch()async functionmain ():Promise <unknown> {try {returnrequest ();} catch {console .log ("error");} finally {console .log ("finally");// @log: finally}}main ().then (() => {console .log ("then");}).catch (() => {console .log ("catch");// @log: catch});
tsfunctionrequest ():Promise <unknown> {throw newError ("error");}// try -> finally -> return -> catch()async functionmain ():Promise <unknown> {try {returnrequest ();} catch {console .log ("error");} finally {console .log ("finally");// @log: finally}}main ().then (() => {console .log ("then");}).catch (() => {console .log ("catch");// @log: catch});
Trong ví dụ như thế này, các giá trị hiển thị sẽ là finally và catch.