SqlStorage issues with get/set of arrays


#1

I am working on prototyping out an application where I would like to use SqlStorage. Currently, I am working through the get/set functionality which seems really simple and clean. The issue I am running into is that the if the array contains objects, I am receiving the following error:

EXCEPTION: Cannot find a differ supporting object '[object Object]'

Here is my code:
Record provider:

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Storage, SqlStorage} from 'ionic/ionic';

@Injectable()
export class Record {
    constructor() {
        this.storage = new Storage(SqlStorage);
        this.storage.set('test', JSON.stringify([
            {
                prop1: "test",
                prop2: "testc",
                prop3: 'test',
                total: "8",
                prop4: "test",
                prop5: "test",
                prop6: "test",
                prop7: true
            }
        ]));
        this.data = null;
    }

    load() {
        if (this.data) {
            // already loaded data
            return Promise.resolve(this.data);
        }

        // don't have the data yet
        return new Promise(resolve => {
            // We're using Angular Http provider to request the data,
            // then on the response it'll map the JSON data to a parsed JS object.
            // Next we process the data and resolve the promise with the new data.
            resolve(
                this.storage.get('test').then(function (result) {
                    return JSON.parse(result);
                }));
        });
    }
}

Page:

import {Page, NavController} from 'ionic/ionic';
import {Record} from 'providers/records/record';

@Page({
    templateUrl: 'build/pages/testpage/testpage.html',
    providers:[Record]
})
export class Testpage {
    constructor(nav:NavController, rec: Record) {
        this.nav = nav;
        this.records = rec.load().then(function(results) {
            this.records;
        });
    }

    method1(record) {
        console.log(record);
    }

    method2(record) {
        console.log(record);
    }
}

Even if the code errors out with the above error, I still get the data array printed to the console.log from the promise resolve in the provider.

Thoughts?


#2

It looks like “this.records” never gets assigned.

try changing

this.records = rec.load().then(function(results) {
    this.records;
});

into

rec.load().then((results) => {
    this.records = results;
});

#3

my mistake…that does solve my problem; however, I am curious why this does not work;

This doesn’t work

 this.rec.load().then(function(records) {
            this.records = records;
        });

This does work

this.rec.load().then((records) => {
            this.records = records;
        });

#4

The value of this changes inside your function because a new scope is created in the asynchronous call and this in your callback function isn’t the same this as on the outside. Yep, it’s a trap and we all fall into it now and then. :slightly_smiling:

Using “fat arrow” notation solves the problem by auto-binding to the parent scope.

Another solution would be to use another variable to reference this, something like:

var foo = this;
this.rec.load().then(function(records) {
    foo.records = records;
});

There is also an option to manually bind this to the scope:

this.rec.load().then(function(records) {
    this.records = records;
}).bind(this);

but I believe that fat arrows are the preferred way to handle it.


#5

I didn’t even think about scoping on the “this”. That is definitely a trap I have fallen for. Got to try and remember that.

Thanks