TypeScript cơ bản cho tester (P3): Module, promise, async/await

⏱︎

Read time:

3–4 minutes
Minh hoạ tester học module async await class và Playwright

Scope: biến dùng được ở đâu?

Scope là phạm vi mà một biến có thể được truy cập. Biến khai báo bên trong function hoặc block thường chỉ sử dụng được trong khu vực đó.

const baseUrl = "https://elitest.vn"; // Biến này dùng được trong cả file

function printLoginUrl() {
  const path = "/login"; // Biến này chỉ tồn tại trong phạm vi của function này
  console.log(`${baseUrl}${path}`);
}

printLoginUrl();
// console.log(path); // Lỗi: không tìm thấy biến "path" bên trên

Module: chia code thành nhiều file

Khi code lớn dần, chúng ta phải tách ra thành các file riêng. export công khai giá trị từ một file; import sử dụng giá trị đó ở file khác.

File test-data.ts:

export const validUser = {    //tiền tố export nghĩa là cho phép các file khác "import" được thằng này
  email: "student@elitest.vn",
  password: "Aa@123456",
};

export function createEmail(prefix: string): string {
  return `${prefix}@elitest.vn`;
}

File login.ts:

import { validUser, createEmail } from "./test-data";   //import 2 biến từ file khác sang

console.log(validUser.email);
console.log(createEmail("student02"));
  • ./test-data là đường dẫn tương đối từ file hiện tại.
  • Tên trong dấu ngoặc nhọn phải khớp với named export.

Xử lý lỗi cơ bản với try/catch

try/catch cho phép code xử lý một lỗi dự kiến thay vì dừng toàn bộ chương trình.

const jsonText = '{ "status": 200 }';

try {   //thử
  const data = JSON.parse(jsonText);   //tạo object từ 1 JSON string
  console.log(data.status);
} catch (error) {  //nếu lỗi thì nhảy vào đây
  console.error("JSON không hợp lệ", error);
}

Promise, async và await (xử lý bất đồng bộ)

Một số công việc không hoàn thành ngay: gọi API, mở trang, click rồi chờ điều hướng hoặc đọc file. JavaScript dùng Promise để biểu diễn kết quả sẽ có trong tương lai.

Mẹo nhớ
Trong TypeScript, khi bạn gọi các hàm như gọi API, đọc file, hoặc các lệnh tương tác trình duyệt (như page.goto(), page.click()), hệ thống không trả về kết quả ngay lập tức mà trả về một Promise (Lời hứa). Từ khóa await chính là hành động bạn ngồi chờ cho đến khi shipper giao hàng xong (lời hứa được thực hiện) rồi mới làm bước tiếp theo.

Tester mới cần nắm bốn ý:

  • Thao tác bất đồng bộ cần thời gian để hoàn thành.
  • await chờ Promise hoàn thành và lấy kết quả.
  • Function chứa await phải có async.
  • Quên await có thể làm các bước chạy sai thứ tự.
function orderFood(): Promise<string> {
  console.log("Đã đặt một chiếc pizza");

  return new Promise((resolve) => {
    setTimeout(() => {
      resolve("Shipper đã giao pizza");
    }, 2000);
  });
}

async function haveDinner(): Promise<void> {
  console.log("Đang chờ đồ ăn...");

  const food = await orderFood();

  console.log(food);
  console.log("Bắt đầu ăn tối");
}

haveDinner();

Promise<string> nghĩa là orderFood() chưa trả món ăn ngay, mà hứa sẽ trả về một chuỗi trong tương lai. setTimeout() mô phỏng hai giây chờ shipper; nhờ await, dòng “Bắt đầu ăn tối” chỉ chạy sau khi pizza đã được giao.

Vì sao quên await gây lỗi?

async function haveDinnerWrong(): Promise<void> {
  orderFood(); // Quên await
  console.log("Bắt đầu ăn dù pizza chưa được giao");
}

async function haveDinnerCorrectly(): Promise<void> {
  await orderFood();
  console.log("Pizza đã được giao, bắt đầu ăn");
}

// haveDinnerWrong();
haveDinnerCorrectly();
Ví dụ
Hãy hình dung await là “đợi bước này hoàn thành rồi mới đi tiếp”. Nó không phải sleep cố định; nó chờ Promise của chính thao tác đó được giải quyết hoặc bị từ chối.

Tóm tắt phần 3

  • Scope xác định nơi một biến có thể được truy cập.
  • export/import giúp chia code thành module.
  • try/catch chỉ nên dùng khi có chiến lược xử lý lỗi rõ ràng.
  • await giúp các thao tác bất đồng bộ chạy đúng thứ tự.