Promises trong JavaScript là gì?

Promise là một đối tượng trong JavaScript đại diện cho một tác vụ bất đồng bộ có thể hoàn thành trong tương lai. Nó cho phép bạn xử lý tác vụ bất đồng bộ một cách rõ ràng và dễ quản lý hơn so với cách dùng callback truyền thống.

Cách hoạt động của Promise:

Một Promise có 3 trạng thái chính:

  1. Pending (Đang chờ): Promise chưa hoàn thành, đang trong quá trình xử lý.
  2. Fulfilled (Hoàn thành): Tác vụ bất đồng bộ thành công, trả về kết quả.
  3. Rejected (Thất bại): Tác vụ bất đồng bộ thất bại, trả về lỗi.

Khi một Promise chuyển từ trạng thái Pending sang Fulfilled hoặc Rejected, trạng thái đó là kết thúc (settled), và không thể thay đổi.

Cú pháp tạo Promise:

const promise = new Promise((resolve, reject) => {
    // Thực hiện tác vụ bất đồng bộ
    const success = true;

    if (success) {
        resolve("Tác vụ thành công!");
    } else {
        reject("Tác vụ thất bại!");
    }
});
  • resolve(value): Hàm được gọi khi tác vụ thành công, trả về giá trị value.
  • reject(error): Hàm được gọi khi tác vụ thất bại, trả về lỗi error.

Sử dụng Promise với .then().catch():

const fetchData = new Promise((resolve, reject) => {
    setTimeout(() => {
        const success = true;

        if (success) {
            resolve("Dữ liệu đã nhận!");
        } else {
            reject("Lỗi khi lấy dữ liệu!");
        }
    }, 2000);
});

fetchData
    .then((data) => {
        console.log(data); // "Dữ liệu đã nhận!"
    })
    .catch((error) => {
        console.error(error); // "Lỗi khi lấy dữ liệu!"
    });

Promise Chaining (Chuỗi Promises):

Promises cho phép bạn liên kết nhiều tác vụ bất đồng bộ theo thứ tự mà không làm lồng mã (callback hell).

new Promise((resolve) => {
    resolve(10);
})
    .then((number) => {
        console.log(number); // 10
        return number * 2;
    })
    .then((number) => {
        console.log(number); // 20
        return number + 5;
    })
    .then((number) => {
        console.log(number); // 25
    });

Promise với async/await:

async/await là cú pháp hiện đại giúp xử lý Promise rõ ràng và dễ hiểu hơn.


function fetchData() {
    return new Promise((resolve) => {
        setTimeout(() => {
            resolve("Dữ liệu đã nhận!");
        }, 2000);
    });
}

async function getData() {
    console.log("Đang lấy dữ liệu...");
    const data = await fetchData(); // Chờ Promise hoàn thành
    console.log(data); // "Dữ liệu đã nhận!"
}

getData();

Tổng quan về các phương thức của Promise:

1. Promise.all():

Chạy nhiều Promise song song, và chỉ trả kết quả khi tất cả đều hoàn thành.

const promise1 = Promise.resolve(10);
const promise2 = Promise.resolve(20);

Promise.all([promise1, promise2]).then((results) => {
    console.log(results); // [10, 20]
});

2. Promise.race():

Trả kết quả của Promise hoàn thành đầu tiên (thành công hoặc thất bại).

const promise1 = new Promise((resolve) => setTimeout(() => resolve("Xong A"), 1000));
const promise2 = new Promise((resolve) => setTimeout(() => resolve("Xong B"), 2000));

Promise.race([promise1, promise2]).then((result) => {
    console.log(result); // "Xong A"
});

3. Promise.allSettled():

Chạy tất cả Promises và trả về kết quả của từng cái (thành công hoặc thất bại).

const promise1 = Promise.resolve("Thành công");
const promise2 = Promise.reject("Thất bại");

Promise.allSettled([promise1, promise2]).then((results) => {
    console.log(results);
    // [{ status: "fulfilled", value: "Thành công" },
    //  { status: "rejected", reason: "Thất bại" }]
});

4. Promise.any():

Trả về giá trị của Promise đầu tiên thành công. Nếu tất cả bị từ chối, nó sẽ trả lỗi.

const promise1 = Promise.reject("Thất bại A");
const promise2 = Promise.resolve("Thành công B");

Promise.any([promise1, promise2]).then((result) => {
    console.log(result); // "Thành công B"
});

Ưu điểm của Promises:

  1. Dễ quản lý hơn callback hell: Giúp mã dễ đọc và logic rõ ràng hơn.
  2. Kết hợp linh hoạt: Cho phép chạy song song hoặc tuần tự các tác vụ bất đồng bộ.

Nhược điểm:

  1. Độ phức tạp: Đối với người mới học, Promises có thể khó hiểu.
  2. Không hỗ trợ tự nhiên xử lý lỗi nhiều cấp: Cần .catch() đúng cách để tránh bỏ sót lỗi.

Tóm lại:

Promise trong JavaScript là công cụ mạnh mẽ để xử lý bất đồng bộ, thay thế các callback truyền thống, giúp mã dễ đọc và bảo trì hơn. Sử dụng Promise kết hợp với async/await hoặc các phương thức như Promise.all, bạn có thể viết mã hiệu quả và rõ ràng hơn.