Search code examples
typescriptionic-frameworkionic2promiseionic-storage

Ionic Storage undefined in promise?


I have an Ionic 2 app that shows the user Items inside Packages in the form of a list. I created a function that retrieves the current Item index inside a Package, it is fired the user launches the app. It checks if the index name-value pair in Ionic Storage (internal) memory is null. In that case, the index is set to 0 and stored in both internal and working memory. Otherwise, the index is retrieved from internal memory and used to set working memory.

However, self.storage.set(myString, '0'); in the code below throws the error TypeError: Cannot call method 'set' of undefined. I checked using console.dir and indeed self.storage was undefined inside the then(...); block. Why is this, and how can I work around it?

Imports, declarations, constructor

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

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

declare var self: ItemStorageService;

@Injectable()
export class ItemStorageService {
    workingMemoryItems: Array<any>;
    workingMemoryIndex: number;
    packageIndex: number;

    constructor(public storage: Storage) {
        self = this;
        self.packageIndex = 0;

        self.initializeIndex().then(
            res => {
                console.log(res);
            },
            err => {
                console.log(err);
            }
        )
    }
// Other methods including initializeIndex()
}

InitializeIndex function

public initializeIndex(): Promise<any> {
    console.dir(self.storage); // Returns Storage object
    var myString = 'index_item_package_' + self.packageIndex;
    return new Promise((resolve, reject) => {
        self.storage.get(myString).then(
            val => {
                if ((val === null) || (val === 'null')) {
                    console.dir(self.storage); // Returns undefined
                    self.storage.set(myString, '0');
                    self.workingMemoryIndex = 0;
                    resolve('Working memory index not found and set to 0');
                } else {
                    self.workingMemoryIndex = val as number;
                    resolve('Working memory index found and set to ' + val);
                }
            },
            err => {
                self.storage.set(myString, 0);
                self.workingMemoryIndex = 0;
                reject('Working memory index not found and set to 0');
            }
        )
    });
}

Solution

  • I believe the reason why this happened is because the global variable self was declared at the top of every one of my pages and services. This means that when I was running self.storage.get(myString), the constructor for ItemStorageService was running and re-initializing self to point at itself.

    The solution to this is not to use self everywhere, but only where it's needed (like inside callback functions) and to make sure to set self = this as close to where it's used as possible.