@Injectable to serve static data across application


#1

I’ve read somewhere that @Injectables are suppose to be singleton. I created one and load a <2mb json file and saved it on a variable. The file is loaded at @App init but when I try to retrieve the data on a @Page its always empty. So I resorted on calling the loadFile() on constructor everytime I want to use the data. Is this the correct behaviour of @Injectable?

@Injectable
export class StaticFileService {
    
    private _persons: Person[] = new Array<Person>();
 
    constructor(private _http:Http){}

    loadFile(){
        this.http.get('data/myFile.json')
            .map(res => res.json())
            .subscribe(res => {
                for (let j in res) {
                    let p = new Person(res[j].name, res[j].area);
                    this._persons.push(p);
                }
           })
     } 

     get persons():Person[] { return this._persons; }
}

#2

If you declare the provider in the @App decorator, i.e:

@App({
  templateUrl: 'build/app.html',
  providers: [MyProvider],
  config: {}
})

then you will be able to access the data throughout the application. If you declare the provider in another component, it creates a new instance of the provider.

However, you also need to make sure that the data has had time to load when you are trying to access it since Http is asynchronous. Check out how the Ionic team does it in the Ionic Conference app, if the data has finished loading in the provider then the data is returned directly, if not it is fetched when the call is made.

EDIT: Had some code open in my editor that does what I’m talking about so I may as well post it!

	getProducts(){

		if(this.products){
			return Promise.resolve(this.products);
		}
		return new Promise((resolve) => {
			this.http.get('assets/products.json').map(res => res.json()).subscribe((data) => {
				this.products = data.products;
				resolve(this.products);
			});
		});

	}

#3

Thanks! That was it!