I would like to save some data fetched from an API so that a user doesn't have to refetch the content when he revisits the page. Also, it helps to persist the scroll position (I don't know if it's the right way to do that though).
Currently, I am saving it in service using a BehaviourSubject and making a request only if the service does not hold any value, in case it does I simply get that value instead of making an HTTP call. And clear the service on user logout.
This is the code
blogs_storage.service.ts
import { Injectable } from '@angular/core';
import { BehaviorSubject, Observable } from 'rxjs';
import { Blog } from './blog.model';
@Injectable({ providedIn: 'root' })
export class BlogStorageService {
private blogs = new BehaviorSubject<Blog[]>(null);
private userBlogs = new BehaviorSubject<Blog[]>(null);
clearStorage() {
this.blogs.next(null);
this.userBlogs.next(null);
}
getBlogs(): BehaviorSubject<Blog[]> {
return this.blogs;
}
getUserBlogs(): BehaviorSubject<Blog[]> {
return this.userBlogs;
}
storeUserBlogs(blogs: Blog[]): void {
this.userBlogs.next(blogs);
}
storeBlogs(blogs: Blog[]): void {
this.blogs.next(blogs);
}
}
blogs.service.ts
import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { BehaviorSubject, catchError, exhaustMap, tap, throwError } from 'rxjs';
import { Blog, NewBlog } from './blog.model';
import { BlogStorageService } from './blogs-storage.service';
@Injectable({ providedIn: 'root' })
export class BlogService {
constructor(
private http: HttpClient,
private blogStorage: BlogStorageService
) {}
fetchAllBlogs() {
const blogs: Blog[] = this.blogStorage.getBlogs().getValue();
if (blogs) {
return this.blogStorage.getBlogs().asObservable();
} else {
return this.http.get<{ data: Blog[]; status: number }>('blogs').pipe(
tap((blogs) => {
this.blogStorage.storeBlogs(blogs.data);
}),
exhaustMap(() => {
return this.blogStorage.getBlogs().asObservable();
})
);
}
}
fetchUserBlogs() {
const blogs: Blog[] = this.blogStorage.getUserBlogs().getValue();
if (blogs) {
return this.blogStorage.getUserBlogs().asObservable();
} else {
return this.http
.get<{ data: Blog[]; status: number }>('users/blogs')
.pipe(
tap((blogs) => {
this.blogStorage.storeUserBlogs(blogs.data);
}),
exhaustMap(() => {
return this.blogStorage.getUserBlogs().asObservable();
})
);
}
}
fetchBlogBySlug(slug: string) {
return this.http.get<{ data: Blog; status: number }>(`blogs/${slug}`);
}
fetchCategoriesList() {
return this.http.get<{
data: { _id: string; title: string; slug: string }[];
status: number;
}>('blogs/category-list');
}
postblog(data: NewBlog) {
return this.http.post('blogs/create', data);
}
getSavedBlogs() {
return this.http.get<{ data: Blog[]; status: number }>('users/savedblogs');
}
saveBlog(slug: string, alreadySaved: boolean) {
return this.http.put(
`users/savedblogs/${slug}/${alreadySaved ? 'unsave' : 'save'}`,
{}
);
}
}
And on logout
logout() {
this.user = null;
this.isAuth.next(false);
this.blogStorage.storeUserBlogs(null);
localStorage.removeItem('userData');
this.router.navigate(['/auth/login']);
}
Is clearing the data like this secure? Also are there any better ways to achieve this behavior?
I am kind of new to angular, so if my implementation has flaws, please let me know.