Issue with accessing storage in Ionic Storage (Angular)

Currently, I am attempting to utilize Ionic storage for the purpose of saving and loading an authentication token that is necessary for accessing the backend API in my application. However, I am encountering difficulties retrieving the value from storage.

Following the instructions on the component GH page: https://github.com/ionic-team/ionic-storage, I have successfully installed ionic storage (Angular version) using the command below:

npm install @ionic/storage-angular

Subsequently, I imported the storage service into my Globals service, which I established as a centralized repository for all global values within my application:

import { Storage } from '@ionic/storage-angular';

@Injectable()
export class Globals {
    private _authenticationToken: string;

    constructor(private storage: Storage) {
        this._authenticationToken = null;
        this.storage.create();        
    }

    (...)

Furthermore, I designed a saveToken function that aims to store the authentication token, already specified within _authenticationToken through another method, in the Ionic storage:

public saveToken(): Promise<void>
{
    console.log("Saving token");
    console.log(this._authenticationToken);
    return this.storage.set("AuthenticationToken", this._authenticationToken)
        .then(value => console.log("token saved."));
}

Upon executing the saveToken function, the outcome is as follows (Disregard the red lines, they pertain to other processes as saveToken operates asynchronously):

https://i.sstatic.net/C3LzI.png

Consequently, the token was successfully saved, with its value visible within the Application Tab in Chrome Dev Tools:

https://i.sstatic.net/t5IK0.png

However, an issue arises when I attempt to retrieve the saved token utilizing the subsequent method, yielding a null value as if the token had not been saved. This action is intended for reinstating the login session when the application is reopened:

public loadToken(): Promise<void>
{
    return this.storage.get("AuthenticationToken")
        .then(val => {
            console.log("token loaded");
            console.log(val);
            this.setToken(val);
        });
}

The aforementioned code leads to the following messages, indicating a failure to retrieve any value from storage:

https://i.sstatic.net/yfxTI.png

While operating the application on the Chrome browser using ionic serve, I initially suspected that the storage might be resetting upon app reloads. Nevertheless, after inspecting the Application Tab, I confirmed that the Authentication Token remains intact.

Answer №1

I encountered a similar issue and was able to resolve it using the following approach:

import { Injectable } from '@angular/core';
import { Storage } from '@ionic/storage-angular';

@Injectable({
  providedIn: 'root'
})
export class StorageService {

  constructor(private _storage: Storage) {
    this._storage.create();
  }

  public async set(key: string, value: any) {
    await this._storage?.set(key, value);
  }

  public async get(key: string): Promise<any> {
    const data = await this._storage?.get(key);
    return data;
  }

  public async remove(key: string): Promise<void>{
    await this._storage?.remove(key);
  }

  public async clear(): Promise<void>{
    await this._storage?.clear();
  }
}

To retrieve the token, I utilize a guard in my case:

import { Injectable } from '@angular/core';
import { ActivatedRouteSnapshot, CanActivate, Router, RouterStateSnapshot } 
from '@angular/router';
import { StorageService } from '../storage/storage.service';

@Injectable({
  providedIn: 'root'
})
export class GuardService implements CanActivate {

  constructor(private router: Router, private storage: StorageService) {}

  async canActivate(route: ActivatedRouteSnapshot, state: RouterStateSnapshot): Promise<boolean> {
    const key = "user";
    const data = await this.storage.get(key);
    if (!data) {
      this.router.navigateByUrl('/login');
      return false;
    } else{
      this.router.navigateByUrl('/home');
      return true;
    }
  }
}

Answer №2

Allow me to present a potential solution and then provide an explanation:

public fetchToken(callback: (response?: any) => void) : void
{
    this.storage.retrieve("AuthenticationToken")
        .then(data => {
            this.setToken(data);
            callback(data);
        });
}
...

this.fetchToken((response?: any) => {
     // your response here
});

Utilizing a callback is one way to obtain the result without altering your internal procedures.

Your inability to retrieve anything stems from attempting to return an asynchronous outcome (a promise) and then(); will consistently yield null. Your answer can be found within the 'then' block.

An alternative approach is as follows (though you will need to integrate the logic where it is called):

public fetchToken() : Promise<any>
{
    return this.storage.retrieve("AuthenticationToken");
}
...

const token = await fetchToken(); // await simplifies the use of 'then()', ensuring you must wait for the result before proceeding.
this.setToken(token);

Sincere regards.

Answer №3

Encountering a similar issue with storage while using a service, I managed to resolve it as follows:

storage.service.ts

 import { Injectable } from '@angular/core';
    import { Storage } from '@ionic/storage-angular';

   @Injectable({
     providedIn: 'root'
    })
   export class StorageService {
     constructor(private _storage: Storage) {
     this._storage.create();
   }

  public async set(key: string, value: any) {
    await this._storage?.set(key, value);
  }

  public async get(key: string): Promise<any> {
    const data = await this._storage?.get(key);
    return data;
  }

  public async remove(key: string): Promise<void> {
    await this._storage?.remove(key);
  }

    public async clear(): Promise<void> {
    await this._storage?.clear();
    } 
   }

app.component.ts

 public data;
 ngOnInit(): void {
this.storage.get('data').then((data) => {
  this.data = data;
}

Following these steps helped me overcome the undefined storage response issue.

Sharing in hopes that it may be helpful to others :)

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

Differences between ng build --prod and ng --build aot in Angular 7

Recently, I successfully built an Angular 7 application using the command ng build --prod. However, I am now facing a dilemma regarding ng build --aot versus ng build --prod. Our application is currently deployed on ..., and although it runs successfully ...

Mastering the art of leveraging generics in conjunction with ngrx actions

Currently, I am in the process of developing an Angular 7 application that utilizes the NGRX store. In our application, we have numerous entities, each with its own dedicated list view. I decided to explore using generics with the NGRX store to avoid writi ...

Angular Universal: Execution of ngAfterViewInit occurring on the server side rather than the client side

While working on my server-rendered Angular application with Angular 17, I ran into a curious issue revolving around the ngAfterViewInit lifecycle hook. The situation arises when I call an init function within ngAfterViewInit, which relies on an API reques ...

Display a loading indicator when loading a lazy loaded module in Angular 2

Here's my situation: I have a menu with various options that should be displayed based on user permissions. The majority of the menu items are contained within modules, and these modules are lazy loaded. This means that when a user clicks on a menu it ...

Displaying HTML content using Typescript

As a newcomer to typescript, I have a question regarding displaying HTML using typescript. Below is the HTML code snippet: <div itemprop="copy-paste-block"> <ul> <li><span style="font-size:11pt;"><span style="font-family ...

The pagination in React using React Query will only trigger a re-render when the window is in

Currently, I am utilizing React-Query with React and have encountered an issue with pagination. The component only renders when the window gains focus. This behavior is demonstrated in the video link below, https://i.sstatic.net/hIkFp.gif The video showc ...

A guide on implementing a "Select All" trigger in mat-select with Angular8/Material

Here is the code I have created: <mat-form-field appearance="outline"> <mat-label>Handler Type</mat-label> <mat-select multiple [(value)]="handlerType"> <mat-option *ngFor="let handler of handlerT ...

Tips for retrieving the value from an angular tag using Selenium

Is there a way to retrieve text content that can be seen on the user interface, but is not part of the HTML structure? https://i.sstatic.net/SdibP.jpg ...

Update the Angular material table with the set filtered results

Currently, I have a functioning Angular Material table with search capabilities. However, I am encountering an issue. The problem lies in the fact that when I navigate from 'route A' to 'route B' and pass a value to the search box in t ...

Managing Scroll Behavior in Ionic

I'm in the process of developing a quiz application using Ionic and Angular. My goal is to display one card at a time, similar to how Instagram and Facebook do it. This means that as users scroll down the app, only one card should be visible on their ...

What is the proper way to conduct unit testing on a function that is invoked in a service's constructor

Is there a way to verify, within the service's spec file, that a function is invoked in the constructor? Consider the following example: @Injectable({ providedIn: 'root' }) export class myService { constructor() { this.myF ...

Angular error: Attempting to reduce an empty array without an initial value

I am encountering an issue with my array being filtered and reduced. getPageComponents(title: string) { this.pageComponents = []; const pageBlock = this.pageComponents.filter((val) => { if (val.page_title === title) { retur ...

Execution of the RxJS pipe Finalize operator initiated prior to Observable finalization

After updating the detailed information of users, I attempted to retrieve the updated user list. Initially, I used this.mediaService.updateImports(): Observable<any> to update the user details. Next, I tried displaying the updated user details us ...

What situations call for the use of 'import * as' in TypeScript?

Attempting to construct a cognitive framework for understanding the functionality of import * as Blah. Take, for instance: import * as StackTrace from 'stacktrace-js'; How does this operation function and in what scenarios should we utilize imp ...

Unusual behavior when importing in Angular 2 using TypeScript

While working on a demo for another question on Stack Overflow, I initially used angular-cli and then switched to Plunker. I noticed a peculiar difference in behavior with the import statement between the two setups. The issue arises with the second impo ...

Deleting and inserting an element in the Document Object Model

I am currently working on developing a framework and need to create a directive called cp-if. Unlike the existing cp-show directive, where I can simply change the visibility of an element to 'none' and then make it visible again, with the cp-if d ...

Error: Trying to break down a non-iterable object is not valid

Currently working on an Ionic React app and encountering the following error: Error: TypeError - Invalid attempt to destructure non-iterable instance Once I run the program, the error occurs at this point: . Shown below is a snippet of my code: import ...

Issue detected in rxjs-compat operator's shareReplay file at line 2, column 10:

I've encountered an issue with the angular material spinner I'm using in my project. The error message is as follows: ERROR in node_modules/rxjs-compat/operator/shareReplay.d.ts(2,10): error TS2305: Module '"D:/ControlCenter/ofservices ...

The type '{ children: Element; }' cannot be assigned to the type 'IntrinsicAttributes & ReactNode'

Encountered this error: Type '{ children: Element; }' is not assignable to type 'IntrinsicAttributes & ReactNode'. export const withAppProvider = (Component: AppComponent) => { return function WrapperComponent(props: any) { ...

The issue arises when attempting to update the input of a child component within a reactive form during the OnInit lifecycle

My dilemma arises in working with data stored in the ngrx entity store, as it gets displayed in chunks based on pagination. The issue lies with rxjs somehow remembering the paging history. For instance, when I fetch the first page of data from the server, ...