3

In my map.service I have coded like this

loadAdminDataDiv (): Observable<any> {
     return this.http.get("static/data/data.json")
                      .map(this.extractData);
  }
private extractData(res) {

      if (res.status < 200 || res.status >= 300) {
        throw new Error('Bad response status: ' + res.status);
      }

      //console.log(res.json());
      this.serviceData =(res.json()) ;
      return this.serviceData || { };
  }

Then injected inside a component as a provider and subscribed like this

getSubscribeData: any;
getAllvaluesFromFiles() {
    this._mapService.loadAdminDataDiv().subscribe(data => {
      this.getSubscribeData = data;

    },
      error => { console.log(error) },
      () => {
        console.log(this.getSubscribeData);  // prints the data 

      }
    );
  }

ngAfterContentInit() {
    this.getAllvaluesFromFiles();
    console.log(this.getSubscribeData); // prints Undefined

  }

Can anyone suggest me a work around with this problem ? My service is working but My subscribed data does not work outside of the subscribe method. I pointed out where I'm having problem. I need to use this this.getSubscribeData throughout my component as a global variable. I dont want to use shared service, Is that possible without using another service. A working code will be helpful :)

And I have to load at least 7 more variable like this. Actually I need to use these variables to pass to d3 objects and into leaflet map and it has to be after some required interactions. Lets say, I have to load leafletmap with this this.getSubscribeData so I will initiate the leaflet map inside the subscribe. but if I want to use this leaflet instance outside of the method what should I do?

pd farhad
  • 6,352
  • 2
  • 28
  • 47

2 Answers2

1

In this code

  ngAfterContentInit() {
    this.getAllvaluesFromFiles();
    console.log(this.getSubscribeData); // prints Undefined
  }

console.log(this.getSubscribeData) is actually before subscribe

subscribe() schedules an async call for Http to make when the current sync thread of execution is completed.
Then your console.log(...) is executed.
When then eventually the response from the server arrives, the callback you passed to subscribe(...) is executed.

To be able to execute some code when the response arrived you can use for example

  getAllvaluesFromFiles() {
    return this._mapService.loadAdminDataDiv()
    .do(data => {
      this.getSubscribeData = data;
    })
    .do(() => {
        console.log(this.getSubscribeData);  // prints the data 
    })
    .catch(error => { 
        console.log(error);
        throw error;
    });
  }

This way an Observable is returned

  ngAfterContentInit() {
    this.getAllvaluesFromFiles()
    .subscribe(data => {
      console.log(this.getSubscribeData); 
    })
  }

This way the calls are properly chained so that console.log(...) is executed after the data is available.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
  • 1
    I know that but the fact is how I am going to solve it :( . I even tried in other Component's Lifecycle hooks(i.e. ngOnInit , ngAfterViewInit) – pd farhad Jun 16 '16 at 08:25
  • You can't solve that with lifecycle hooks. You can only solve that by properly chain calls that use `Observable` or `Promise`. For `Promise` it's `.then()` instead of `subscribe()`. See my updated answer. – Günter Zöchbauer Jun 16 '16 at 08:28
  • 1
    Is there any typo here in your code `return this._mapService.loadAdminDataDiv() do.subscribe(data => { this.getSubscribeData = data; })` It is not working for me – pd farhad Jun 16 '16 at 08:32
  • Yup, sorry. There is a `.` missing - fixed. – Günter Zöchbauer Jun 16 '16 at 08:36
  • 1
    Property 'subscribe' does not exist on type 'DoSignature' , when I typed correctly :) – pd farhad Jun 16 '16 at 08:43
  • Sorry, there was more than a missing `.`. I hope it is fixed now. – Günter Zöchbauer Jun 16 '16 at 08:46
  • So whenever I need to use this `this.getSubscribeData` I have to subscribe ? – pd farhad Jun 16 '16 at 08:54
  • Yes. Without `subscribe()` the call won't be made. If you do the `subscribe()` inside `getAllvaluesFromFiles()` you don't get a way to chain additional code you want to execute when the response arrives. – Günter Zöchbauer Jun 16 '16 at 08:56
  • I accepted your answer but I am still puzzled . Can You please check last para of my updated question :) – pd farhad Jun 16 '16 at 14:01
  • Prose is quite abstract. It's hard for me what the exact problem is that you are struggling with. I understand that you are not yet familiar with async programming. Async is quite common in the browser (because there are no threads). Maybe http://blog.thoughtram.io/angular/2016/01/06/taking-advantage-of-observables-in-angular2.html provides some helpful insight. – Günter Zöchbauer Jun 16 '16 at 14:07
0

Here I got another way... I used static keyword for solving this problem...

getSubscribeData: any;
getAllvaluesFromFiles() {
this._mapService.loadAdminDataDiv().subscribe(data => {
      this.getSubscribeData = data;
      YOUR_CLASSNAME.setSubscribeData(data);
    },
    error => { console.log(error) },
    () => {
        console.log(this.getSubscribeData);  // prints the data 
      }
    );
}
ngAfterContentInit() {
this.getAllvaluesFromFiles();
 console.log(this.getSubscribeData); // prints Undefined
 console.log(YOUR_CLASSNAME.subscribeData); // prints
}

static subscribeData:any;
static setSubscribeData(data){
   YOUR_CLASSNAME.subscribeData=data;
}

try to use this ... hope this will help you

sajal rajabhoj
  • 507
  • 4
  • 14