使用 Angular 进行客户端缓存
应用程序向用户显示有用信息的时间对用户体验有很大影响。因此,我认为作为软件开发者,我们有责任实现一些机制,尽可能减少加载时间。
在本文中,我将向您展示如何使用 Angular 实现客户端缓存。
 读完本文后,您将能够像这样缓存您的 http 请求:
return this._http.get<Product[]>({ url: 'https://example-api/products', cacheMins: 5 })
对于此实现,我们需要:
- 缓存服务:此服务主要有两个用途: 
  - 将数据保存在本地存储中(有有效期)
- 从本地存储加载数据。
 
- 自定义http-client 服务:此服务将在底层使用 Angular HttpClient,但也将使用上面提到的缓存服务从本地存储获取和保存数据。
缓存.服务.ts
import { Injectable } from '@angular/core'
@Injectable()
export class CacheService {
    constructor() { }
    save(options: LocalStorageSaveOptions) {
        // Set default values for optionals
        options.expirationMins = options.expirationMins || 0
        // Set expiration date in miliseconds
        const expirationMS = options.expirationMins !== 0 ? options.expirationMins * 60 * 1000 : 0
        const record = {
            value: typeof options.data === 'string' ? options.data : JSON.stringify(options.data),
            expiration: expirationMS !== 0 ? new Date().getTime() + expirationMS : null,
            hasExpiration: expirationMS !== 0 ? true : false
        }
        localStorage.setItem(options.key, JSON.stringify(record))
    }
    load(key: string) {
        // Get cached data from localstorage
        const item = localStorage.getItem(key)
        if (item !== null) {
            const record = JSON.parse(item)
            const now = new Date().getTime()
            // Expired data will return null
            if (!record || (record.hasExpiration && record.expiration <= now)) {
                return null
            } else {
                return JSON.parse(record.value)
            }
        }
        return null
    }
    remove(key: string) {
        localStorage.removeItem(key)
    }
    cleanLocalStorage() {
        localStorage.clear()
    }
}
export class LocalStorageSaveOptions {
    key: string
    data: any
    expirationMins?: number
}
http-客户端.服务.ts
import { Injectable } from '@angular/core'
import { HttpClient } from '@angular/common/http'
import { CacheService } from './cache.service'
import { Observable, of } from 'rxjs'
import { switchMap } from 'rxjs/operators'
export enum Verbs {
    GET = 'GET',
    PUT = 'PUT',
    POST = 'POST',
    DELETE = 'DELETE'
}
@Injectable()
export class HttpClientService {
    constructor(
        private http: HttpClient,
        private _cacheService: CacheService,
    ) { }
    get<T>(options: HttpOptions): Observable<T> {
        return this.httpCall(Verbs.GET, options)
    }
    delete<T>(options: HttpOptions): Observable<T> {
        return this.httpCall(Verbs.DELETE, options)
    }
    post<T>(options: HttpOptions): Observable<T> {
        return this.httpCall(Verbs.POST, options)
    }
    put<T>(options: HttpOptions): Observable<T> {
        return this.httpCall(Verbs.PUT, options)
    }
    private httpCall<T>(verb: Verbs, options: HttpOptions): Observable<T> {
        // Setup default values
        options.body = options.body || null
        options.cacheMins = options.cacheMins || 0
        if (options.cacheMins > 0) {
            // Get data from cache
            const data = this._cacheService.load(options.url)
            // Return data from cache
            if (data !== null) {
                return of<T>(data)
            }
        }
        return this.http.request<T>(verb, options.url, {
            body: options.body
        })
            .pipe(
                switchMap(response => {
                    if (options.cacheMins > 0) {
                        // Data will be cached
                        this._cacheService.save({
                            key: options.url,
                            data: response,
                            expirationMins: options.cacheMins
                        })
                    }
                    return of<T>(response)
                })
            )
    }
}
export class HttpOptions {
    url: string
    body?: any
    cacheMins?: number
}
现在,假设我们有一个产品服务,用于从 API 中检索产品列表。在此服务中,我们将使用最近创建的 http-client 服务发出请求,并将数据在 localstorage 中保存 5 分钟:
// product.service.ts
import { Injectable } from '@angular/core'
import { HttpClientService } from './http-client.service'
import { Observable } from 'rxjs'
@Injectable()
export class ProductService {
    constructor(
        private _http: HttpClientService
    ) { }
    getAll(): Observable<Product[]> {
        return this._http
            .get<Product[]>({ url: 'https://example-api/products', cacheMins: 5 })
    }
}
export class Product {
    name: string
    description: string
    price: number
    available: boolean
}
 后端开发教程 - Java、Spring Boot 实战 - msg200.com
            后端开发教程 - Java、Spring Boot 实战 - msg200.com