Managing the Cache in IONIC2

After developing an App using IONIC 2, I realized that all my pages require loading through REST API. This can be frustrating as they get reloaded in every tab even when there are no updates.

To improve this issue, I am planning to implement a caching system in my App. The idea is to save every http request after the first time along with the current timestamp, and then load the content through the REST API only if it has been more than 2 hours since the last request.

I tried using a plugin called https://github.com/Nodonisko/ionic-cache, but unfortunately, I encountered some errors after installation.

While researching, I found that using Sqlite for caching might be a better option, but I am not entirely sure about it. Any suggestions from experts would be greatly appreciated.

Below is the code for my home page:

import { WebService } from '../shared/services/web.service';

@Component({
    selector: 'page-home',
    templateUrl: 'home.html',
    providers: [ WebService ]
})

constructor(
        public navController: NavController,
        private webService: WebService ) {}
loadPosts() {
this.webService.getPosts(query)
                .subscribe(data => {
                        key.posts = data;                       
                        loader.dismiss();
                    }, (err) => {
                        //Fail and log the err in console
                        loader.dismiss();
                        console.log("Some Issue");
                        let toast = this.toastController.create({
                            message: 'There is some issue with network',
                            duration: 10000
                        });
                        toast.present();
                    });
}

And here is the code for my service provider page:

    import { Injectable } from '@angular/core';
    import { Http } from '@angular/http';
    import { Config } from '../../../../app/app.config';
    import 'rxjs/add/operator/map';

    @Injectable()
    export class WordpressService {
        constructor(private storage: Storage, private http: Http, private config: Config ) {}

        public getPosts(query) {
            query = this.transformRequest(query);
            let url = this.config.webApiUrl + `/allposts?${query}&_embed`;
            return this.http.get(url)
            .map(result => {
                return result.json();
            });    
        }
}

Looking forward to expert advice. Thanks, Sanny

Answer №1

I believe that Ionic's Storage is sufficient for this task, however, if you prefer to use Sqlite, you can easily adapt the following code to incorporate it.

This implementation is a simplified version that I have utilized in a recent project. If you encounter any issues with copying and pasting the code, please let me know...

// Angular
import { Injectable } from '@angular/core';

export class CacheItemModel {

    constructor(public timestamp: number, public data: any) { }

    public isValid(): boolean {
        if (!this.data) {
            return false;
        }

        let age = Date.now() - this.timestamp;
        return age <= 7200000; // Two hours in ms
    }
}

@Injectable()
export class CacheService {

    private cache: Map<string, CacheItemModel>;

    constructor() {
        this.cache = new Map<string, CacheItemModel>();
    }

    public get(url: string): any {
        let cacheItem = this.cache.get(url);
        if (cacheItem && cacheItem.isValid()) {
            console.log(`[Cache]: obtained response from ${url} from the cache`);
            return cacheItem.data;
        }

        console.log(`[Cache]: empty or expired for data from ${url}`);
        return null;
    }

    public set(url: string, data: any): void {
        let cacheItem = new CacheItemModel(Date.now(), data);
        this.cache.set(url, cacheItem);
        console.log(`[Cache]: saved data from ${url} in the cache`);
    }
}

The code provides a clear explanation... Essentially, we utilize a CacheItemModel to store the data to be cached along with a timestamp for validity checks. By using the type any for the data, we are able to store various types of data.

Our cache is represented as a

Map<string, CacheItemModel>
; where the key corresponds to the url from which we retrieve the data. For example, it could be something like .../api/products or .../api/products/5.

When utilizing it:

public getData(url: string): Observable<any> {
    let cachedData = this.cacheService.get(url);

    return cachedData
        ? Observable.of(cachedData)
        : this.http.get(url)
            .map(res => res.json())
            .map(res => {
                // Save the data in the cache for future use
                this.cacheService.set(url, res);
                return res;
            });
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The Google APIs sheet API is throwing an error message stating "Invalid grant: account not found"

I need to retrieve data from a spreadsheet using the Sheet API. After setting up a project in Google Cloud Platform and creating a service account, I granted the account permission to edit the spreadsheet. I then downloaded the credentials in JSON format. ...

Refresh an Angular page automatically

Having a small issue in my angular application. The problem arises on the first page where I display a table listing all employees along with a "Create New Employee" button that opens a form for adding a new employee. However, after submitting the form and ...

What is the process for setting up a node test launch configuration?

I have some "node 18 test runner" tests ready to be executed. I can run them using the following command: node --loader tsx --test tests/**/*.ts To debug these tests in vscode, I realized that I need to set up a configuration entry in my launch.json. But ...

Technique in CSS/SASS to repair a div

Seeking a solution for fixing divs with text in CSS. I am aware of the background-attachment: fixed; property which creates a fancy effect. Is there a similar property to "fix" divs with text or how can this be achieved in Typescript? Your insight would be ...

Unable to create resource in nestjs due to typeScript compatibility issue

Encountered an Error: TypeError: Cannot access 'properties' property of undefined Failed to execute command: node @nestjs/schematics:resource --name=post --no-dry-run --language="ts" --sourceRoot="src" --spec Attempts made ...

Strange error message regarding ES6 promises that is difficult to interpret

Snippet getToken(authCode: string): Promise<Token> { return fetch(tokenUrl, { method: "POST" }).then(res => res.json()).then(json => { if (json["error"]) { return Promise.reject(json); } return new Token ...

Tips for Observing angular forkJoin for multiple responses during unit testing with Jasmine

Currently, I am focusing on unit testing and I have a function that makes multiple API calls simultaneously. Although I have used spyOn on the service function, I am facing difficulty in returning multiple responses. Can anyone provide guidance on where I ...

Checking constructor arguments and code style issues

I need to ensure that the constructor parameter is validated correctly when an instance of a class is created. The parameter must be an object that contains exactly all the properties, with the appropriate types as specified in the class definition. If t ...

Unexpected behavior with the ion-datetime time picker on an Android device

I am encountering challenges with a Date and Time entry feature in my Angular/Ionic application that involves date pickers. When I tap on the Time field, the time picker opens. Everything works perfectly in my browser - I can select a time, spin the value ...

An issue was encountered in the node_modules folder while attempting to access the 'Exclude' name in the lodash collection file. The error message reads: (1783,24): error TS2304: Cannot

When attempting to execute the ng serve command, I encountered an error. See below for more details. ERROR in node_modules/@types/lodash/common/collection.d.ts(1783,24): error TS2304: Cannot find name 'Exclude'. ... (error list continued) .. ...

Converting a Promise to an Observable in Angular using Typescript

I have a working method that functions as intended: getdata(): Promise<any> { let query = `SELECT * FROM table`; return new Promise((resolve, reject) => { this.db.query(query, (error, rows) => { if(error) reject(error); ...

Angular application experiences issues with persistent login when using Cypress.io

Recently, I decided to follow a tutorial provided by Auth0 (https://auth0.com/blog/end-to-end-testing-with-cypress-and-auth0/) in order to utilize Cypress.io. However, despite my efforts, I have been unable to retain a successful sign-in with Cypress. Ini ...

TypeScript interface designed to capture objects containing a flexible number of values

In my possession is an object that looks like the following: { "0001": "a", "0002": "b", "0003": "c", ... } Is it possible for me to create a TypeScript interface that accurately represents this type? ...

Having trouble applying [formControl] to a set of radio buttons in Angular2

Currently, I am encountering an issue with a list of groups of radio buttons in Angular2. My objective is to bind the value of each group of radio buttons using [formControl]. However, when implementing this, the radio buttons seem to lose their normal mut ...

Reacting to Appwrite events in a React Native environment

My React Native application encounters an error when subscribing to realtime events. The error message reads as follows: ERROR Error: URLSearchParams.set is not implemented, js engine: hermes. appwriteClient .subscribe( `databases.${APPWRITE_DATAB ...

Launching the API using Modal in Angular 6

I'm seeking assistance on how to trigger a delete API request after confirming in a modal dialog using Angular. onDelete(id: number) { this.confirmationDialogService.confirm('Confirm Delete', 'Do you really want to delete this ...

What is the method for inserting two dashes within a number?

For the output, I am looking to showcase a number in the following format => 979-9638403-03. At present, the number appears like this => 979963840303. portfolio.ts export class Portfolio { ... DEPO: number; /* DEPO */ const ...

Replace i18next property type in React for language setting

We have decided to implement multilanguage support in our app and encountered an issue with function execution. const someFunction = (lang: string, url: string) => any If we mistakenly execute the function like this: someFunction('/some/url', ...

Instructions for setting up qtip2 tooltip with npm in an Angular 2 project

Struggling to integrate qtip2 into my Angular 2 app, encountering errors like this After extensive Google searches, I could not find a definitive solution for installing the qtip2 JQuery plugin via npm to enable tooltips. Even after updating JQuery to ve ...

Vue-i18n does not offer a default export option

Hello everyone! This is my first experience using vue-i18n in a project with TypeScript + Vue. Following the instructions from the official site, I installed it using yarn install vue-i18n. Next, I tried to import it into main.ts using import VueI18n from ...