Provider returning undefined the first time, but the correct data the second time


#1

Hi, Guys,

I have created a provider that gets city name in select box, but the problem is, that on the first click of the button that activates the provider and getting everything from the server, the first return is undefined, while the second click returns the correct data. Please help me out on that.

Provider:

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

import { Http, Headers, RequestOptions, Response } from "@angular/http";
import 'rxjs/add/operator/map';

@Injectable()
export class ViewCitiesNameProvider {


	allCitiesName: any;

  constructor(/*public http: HttpClient*/ public http: Http ) {
this.allCityNameLoad()
  }

allCityNameLoad() {

        this.http.get("http://www.mydomain.com/append/index.php/allcityname")
      .subscribe(data => {
        let  dataTemp=data.json()
        let response = dataTemp.code;
        this.allCitiesName=dataTemp.viewCityName;;
      }, error => {
        // Error getting the data
        console.log(error);
      });

}
loadAll(){
    return Promise.resolve(this.allCitiesName);
  };
}

TS File of the Page, Where I want to Show city name

import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';

import { Http, Headers, RequestOptions,Response } from "@angular/http";
import 'rxjs/add/operator/map'

import { ViewCitiesNameProvider } from '../../providers/view-cities-name/view-cities-name';

@Component({
  selector: 'page-about-us',
  templateUrl: 'about-us.html',
})
export class AboutUsPage {

	cityName:any;

  constructor(public navCtrl: NavController, public navParams: NavParams, public http: Http, public cityNameService: ViewCitiesNameProvider) {
  
}

  ionViewDidLoad() {
   this.cityNameService.loadAll().then(result => {
      this.cityName = result;
      alert(JSON.stringify(this.cityName))
    });
  }
}

HTML File of the Page, Where I want to Show city name in select box

 <ion-item>
    <ion-label color="custom" floating>Select City*</ion-label>
    <ion-select [(ngModel)]="offerSellerName" #selectstate (ionChange)="getstateid(selectstate.value)">
      <ion-option *ngFor="let name of cityName" [value] = "name.city_id">{{name.city_name}}</ion-option>
    </ion-select>
  </ion-item>

#2

Don’t subscribe in providers. Return Observables from providers, and do the subscribing in pages. Following that rule will prevent you from making mistakes like this one. Nobody outside of the subscribe block inside allCityNameLoad can ever have any clue as to when it has finished, the way it is written now.


#3

Can you make the changes in my code…because I am not much more friendlier with provider.


#4

You can try like this

 constructor(private http: Http) {
    this.data = null;
  }
load() {
    if (this.data) {
      return Promise.resolve(this.data);
    }
 
    return new Promise(resolve => {
      this.http.get("http://www.mydomain.com/append/index.php/allcityname")
        .map(res => res.json())
        .subscribe(data => {
          this.data = data;
          resolve(this.data);
        });
    });
  }

I hope your problem will be solved
Good Luck


#5

Hello Friend! Thanks for the reply

I made the change as you have suggested, but it showing a different type error from the previous one.

runtime Error
Error trying to diff '[object Object]'. Only arrays and iterables are allowed

#6

Please stop promoting this (doggedly persistent) antipattern stew. Don’t explicitly instantiate Promises when dealing with HttpClient; use its Observables. Follow the idioms in here instead.


#7

Hi, This way I have solve my problem

Provider

//import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';

import { Http, Headers, RequestOptions, Response } from "@angular/http";
import 'rxjs/add/operator/map';

@Injectable()
export class ViewCitiesNameProvider {

	allCitiesName:any = [];

  constructor(/*public http: HttpClient*/ public http: Http ) {
     this.allCitiesName = null;
  }

  getCity() {
 
      return this.http.get("http://www.mydomain.com/append/index.php/allcityname")
      .map(res => res.json());
   
  }

}

TS File of the Page, Where I want to Show city name

import { Component } from '@angular/core';
import { NavController, NavParams, Loading, LoadingController, } from 'ionic-angular';

import { Http, Headers, RequestOptions,Response } from "@angular/http";
import 'rxjs/add/operator/map'

import { ViewCitiesNameProvider } from '../../providers/view-cities-name/view-cities-name';

@Component({
  selector: 'page-about-us',
  templateUrl: 'about-us.html',
})
export class AboutUsPage {

  aboutustext: any;
  cityName:any;
  loading: Loading;

  constructor(public navCtrl: NavController, public navParams: NavParams, public http: Http, public cityNameService: ViewCitiesNameProvider, public loadingCtrl:LoadingController) {
  
}

  ionViewDidLoad() {
 
    this.cityNameService.getCity()
    .subscribe(data=>{
      this.cityName = data.viewCityName;
      alert(JSON.stringify(this.cityName))
    })
  }
}

#8

If you use HttpClient instead, you wouldn’t need the map or the json() call.