Nếu bạn đang tìm cách triển khai bộ nhớ đệm cho các Promise, bài viết này sẽ rất hữu ích cho bạn.
Tình Huống Sử Dụng: Lưu Kết Quả Bất Đồng Bộ
Chúng ta sẽ lưu lại kết quả của các cuộc gọi API bất đồng bộ và giữ chúng trong bộ nhớ đệm. Ví dụ, khi bạn gọi một API để lấy thông tin bài viết theo ID:
javascript
const getPostById = async (postId): Promise<Post> => {
const post = await (await fetch(`/api/v1/posts/${postId}`)).json();
return post;
}
Cách này hoàn toàn bình thường, nhưng nếu API mất nhiều thời gian để phản hồi, chúng ta có thể gặp vấn đề về hiệu suất. Nếu bạn thường xuyên gọi API này để lấy thông tin bài viết, việc lưu trữ kết quả vào bộ nhớ đệm sẽ rất hữu ích.
Giải Pháp Thông Thường
Dưới đây là cách giải quyết thường thấy:
javascript
const caching = new Map<string, Post>();
const getPostById = async (postId): Promise<Post> => {
if (!caching.has(postId)) {
const post = await (await fetch(`/api/v1/posts/${postId}`)).json();
caching.set(postId, post);
}
return caching.get(postId);
}
Trong đoạn mã này, chúng ta sử dụng một Map
để lưu trữ kết quả từ API. Nếu bài viết đã được lưu trong bộ nhớ đệm, chúng ta sẽ trả về kết quả từ đó thay vì gọi lại API. Điều này giúp tiết kiệm thời gian và tài nguyên.
Khái Niệm Singleton Promise
Cách làm này còn được gọi là Singleton Promise. Tương tự như mẫu thiết kế Singleton, nếu bạn gọi cùng một Promise với cùng một ID, bạn sẽ nhận được thông tin giống nhau từ bộ nhớ đệm. Ví dụ:
javascript
Promise.all([
getPostById("bai-viet-1"),
getPostById("bai-viet-1"),
]);
Trong trường hợp này, bạn sẽ không gặp bất kỳ vấn đề nào khi truy vấn.
Bộ Nhớ Đệm Promise
Từ một góc độ khác, việc triển khai bộ nhớ đệm này thực chất là ghi nhớ kết quả của hàm getPostById()
. Khi nhận đầu vào mà chúng ta đã thấy trước đó, chúng ta chỉ cần trả lại kết quả đã lưu.
Tuy nhiên, có nhiều thư viện giúp việc ghi nhớ trở nên đơn giản hơn, như lodash.
Giải Pháp Đơn Giản Hơn
Chúng ta có thể đơn giản hóa giải pháp của mình bằng cách sử dụng lodash:
javascript
import _ from 'lodash';
const getPostById = _.memoize(async (postId: string): Promise<Post> => {
const post = await (await fetch(`/api/v1/posts/${postId}`)).json();
return post;
});
Với cách này, chúng ta không cần phải triển khai bộ nhớ đệm từ đầu, mà chỉ cần sử dụng hàm _.memoize
để tự động xử lý việc lưu trữ kết quả. Rất đơn giản và hiệu quả!