×

Cách sử dụng Promises để xử lý bất đồng bộ

Trong lập trình JavaScript, một trong những thách thức lớn nhất là xử lý các tác vụ bất đồng bộ. Trước đây, các lập trình viên thường sử dụng callback để quản lý việc này. Mặc dù callback có thể giải quyết vấn đề ở một mức độ nào đó, nhưng nó dẫn đến vấn đề gọi là "callback hell" khi phải lồng nhiều callback với nhau. Promises ra đời như một giải pháp mạnh mẽ và linh hoạt hơn để xử lý bất đồng bộ.

Promises là gì?

Promises là một đối tượng đại diện cho một giá trị không đồng bộ trong tương lai. Promises có thể ở một trong ba trạng thái:

  1. Pending (đang chờ): Giá trị chưa được xác định.
  2. Fulfilled (đã hoàn thành): Giá trị đã được xác định.
  3. Rejected (bị từ chối): Có lỗi xảy ra hoặc giá trị không thể xác định.

Cách khởi tạo Promises

Để tạo một Promise, bạn sử dụng từ khóa new Promise kèm theo một hàm tham số có hai callback chức năng: resolvereject.

let promise = new Promise((resolve, reject) => {
  // Một số tác vụ bất đồng bộ
  let success = true; // Giả sử tác vụ thành công
   
  if (success) {
    resolve("Tác vụ thành công!");
  } else {
    reject("Tác vụ thất bại!");
  }
});

Sử dụng then, catch, và finally

Một trong những lợi ích lớn nhất của Promises là khả năng xâu chuỗi các tác vụ bất đồng bộ.

promise
  .then((message) => {
    console.log(message); // Output: Tác vụ thành công!
  })
  .catch((error) => {
    console.error(error); // If something goes wrong
  })
  .finally(() => {
    console.log("Tác vụ đã hoàn thành.");
  });

Các phương thức hữu ích của Promises

Promise.all

Phương thức này cho phép bạn đợi nhiều Promise hoàn thành trước khi thực hiện tiếp tục.

let promise1 = Promise.resolve(3);
let promise2 = 42;
let promise3 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'foo');
});

Promise.all([promise1, promise2, promise3]).then(values => {
  console.log(values); // Output: [3, 42, "foo"]
});

Promise.race

Phương thức này trả về Promise đầu tiên được hoàn thành.

let promise1 = new Promise((resolve, reject) => {
  setTimeout(resolve, 500, 'one');
});
let promise2 = new Promise((resolve, reject) => {
  setTimeout(resolve, 100, 'two');
});

Promise.race([promise1, promise2]).then(value => {
  console.log(value); // Output: two
});

Promise.allSettled

Phương thức này trả về một Promise hoàn thành khi tất cả các Promise đã được giải quyết, bất kể chúng được hoàn thành hay bị từ chối.

const promises = [
  Promise.resolve(1),
  Promise.reject('Lỗi'),
  Promise.resolve(2),
];

Promise.allSettled(promises).then((results) => {
  results.forEach((result) => console.log(result.status));
  // Output:
  // fulfilled
  // rejected
  // fulfilled
});

Promise.any

Phương thức này trả về Promise đầu tiên đã giải quyết thành công và bỏ qua các Promise bị từ chối.

const promises = [
  Promise.reject(0),
  Promise.resolve(1),
  Promise.resolve(2),
];
Promise.any(promises).then(value => {
  console.log(value); // Output: 1
}).catch(err => {
  console.log("Tất cả các promises đều thất bại.");
});

Kết hợp Promises với Asynchronous Function

ES8 đã giới thiệu từ khóa async/await để làm cho việc làm việc với Promises dễ dàng hơn. Từ khóa async biến một hàm trở thành một Promise, và await đình chỉ thực thi của hàm cho đến khi Promise được giải quyết.

async function demo() {
  try {
    let result = await promise;
    console.log(result); // Output: Tác vụ thành công!
  } catch (error) {
    console.error(error); // If something goes wrong
  } finally {
    console.log("Tác vụ đã hoàn thành."); 
  }
}

Kết luận

Promises đã mang lại một cải tiến đáng kể trong việc xử lý bất đồng bộ trong JavaScript. Bằng cách sử dụng Promises cùng với async/await, code của bạn sẽ trở nên gọn gàng hơn, dễ đọc hơn và dễ bảo trì hơn. Hãy tận dụng các phương thức Promises để tăng hiệu quả xử lý bất đồng bộ trong các dự án của bạn.

Comments