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ó giống như một lời hứa: “Tôi hứa sẽ trả kết quả cho bạn khi tác vụ hoàn thành”. Một Promise có thể ở một trong ba trạng thái sau:
- Pending (đang chờ): trạng thái ban đầu, chưa hoàn thành hoặc bị từ chối.
- Fulfilled (hoàn thành): tác vụ đã hoàn thành thành công.
- Rejected (bị từ chối): tác vụ đã thất bại.
Tại sao cần sử dụng Promise?
Trước khi Promise xuất hiện, callback được sử dụng để xử lý bất đồng bộ. Tuy nhiên, việc lồng ghép nhiều callback dẫn đến “Callback Hell”, khiến code khó đọc và khó bảo trì. Promise giải quyết vấn đề này bằng cách cung cấp cách viết code rõ ràng và tuyến tính, dễ dàng quản lý các tác vụ bất đồng bộ và xử lý lỗi hơn.
Hướng dẫn sử dụng Promise trong JavaScript
Tạo một Promise
Để tạo một Promise, bạn sẽ sử dụng new Promise
, truyền vào một hàm executor với hai tham số là resolve
và reject
. resolve
được gọi khi Promise hoàn thành thành công, reject
được gọi khi Promise bị từ chối.
const promise = new Promise((resolve, reject) => {
setTimeout(() => {
const success = true;
if (success) {
resolve('Success!');
} else {
reject('Failed!');
}
}, 1000);
});
Trong ví dụ này, sau 1 giây, Promise sẽ được hoàn thành với kết quả “Success!” hoặc bị từ chối với “Failed!”.
Xử lý kết quả với .then() và .catch()
Để nhận kết quả từ một Promise, bạn có thể sử dụng phương thức .then()
và .catch()
. .then(onFulfilled)
được gọi khi Promise được hoàn thành, .catch(onRejected)
được gọi khi Promise bị từ chối.
promise
.then((result) => {
console.log(result); // "Success!"
})
.catch((error) => {
console.error(error); // "Failed!"
});
Chaining Promises (Nối chuỗi Promise)
Bạn có thể nối chuỗi các Promise bằng cách trả về một Promise trong .then()
.
firstPromise()
.then((result1) => {
return secondPromise(result1);
})
.then((result2) => {
console.log(result2);
})
.catch((error) => {
console.error(error);
});
Sử dụng Promise.all
Promise.all
cho phép chúng ta chạy nhiều Promise song song và nhận kết quả khi tất cả đều hoàn thành.
const promise1 = fetchData1();
const promise2 = fetchData2();
Promise.all([promise1, promise2])
.then(([result1, result2]) => {
console.log(result1, result2);
})
.catch((error) => {
console.error(error);
});
Luôn xử lý lỗi bằng cách sử dụng .catch()
. Nếu bạn bỏ qua, lỗi có thể không được phát hiện và gây ra những vấn đề khó debug.
Hướng dẫn sử dụng Promise trong React
Trong React, thường cần thực hiện các tác vụ bất đồng bộ như gọi API để lấy dữ liệu. Sử dụng Promise giúp quản lý những tác vụ này một cách hiệu quả.
Sử dụng fetch API với Promise
fetch
là một API tích hợp trong JavaScript để lấy dữ liệu, và nó trả về một Promise.
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => {
console.log(data);
})
.catch((error) => {
console.error('Lỗi:', error);
});
Trong ví dụ này, chúng ta gọi đến API tại: https://jsonplaceholder.typicode.com/users
để lấy danh sách người dùng.
Sử dụng Promise, useEffect trong component
import React, { useState, useEffect } from 'react';
function UserList() {
const [users, setUsers] = useState(null);
useEffect(() => {
fetch('https://jsonplaceholder.typicode.com/users')
.then((response) => response.json())
.then((data) => {
setUsers(data);
})
.catch((error) => {
console.error('Lỗi:', error);
});
}, []);
return (
<div>
{users ? (
<ul>
{users.map((user) => (
<li key={user.id}>{user.name}</li>
))}
</ul>
) : (
<div>Loading...</div>
)}
</div>
);
}
export default UserList;
useEffect
với dependencies rỗng[]
sẽ chỉ chạy một lần khi component được mount.- Sử dụng
fetch
để gọi API và cập nhật stateusers
khi nhận được kết quả.
So sánh Promise và Async/Await
Async/Await là một cú pháp mới dựa trên Promise, giúp code trông giống như mã đồng bộ, dễ đọc và hiểu hơn. Nó sử dụng try...catch
để xử lý lỗi và tránh việc lồng ghép quá nhiều .then()
. Tuy nhiên, việc sử dụng Async/Await cũng yêu cầu bạn hiểu rõ về Promise. Sử dụng Async/Await khi bạn muốn code trông giống như đồng bộ, dễ đọc và cần thực hiện các tác vụ bất đồng bộ tuần tự. Sử dụng Promise khi bạn cần quản lý nhiều tác vụ bất đồng bộ cùng lúc và cần sử dụng các phương thức như: Promise.all
, Promise.race
.