1

So in normal javascript if I wanted to assign a value to a variable and then use that value outside of a function it would be done by declaring the variable first and then define it's value in the function. I'm brand new to typescript and angular so I am missing how to do this.

In the code below I am trying to get the value from a method in a service and then pass that value into my return. (I hope that makes sense). However I keep getting undefined on console.log(url) with no other errors.

emailsAPI() {
    let url: any  
    this.apiUrlsService.urlsAPI().subscribe(
        data => {
            this.results = data
            url = this.results.emails
        }
    );
    console.log(url)
    return this.http.get('assets/api/email_list.json')
}

api-urls service:

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

@Injectable()
export class ApiUrlsService {

    constructor(
        private http: HttpClient
    ) { }

    urlsAPI () {
        return this.http.get('assets/api/api_urls.json')
    }

}
Sandra Willford
  • 3,459
  • 11
  • 49
  • 96
  • 1
    https://stackoverflow.com/questions/39295854/angular-2-how-to-return-data-from-subscribe and https://stackoverflow.com/questions/43055706/how-do-i-return-the-response-from-an-observable-http-async-call-in-angular2 – AT82 Dec 03 '17 at 17:41
  • What is the purpose of sending http get request ? The point from where you are calling this service do you want the emails or the result of httpget? – Ankit Kapoor Dec 03 '17 at 18:32
  • @AnkitKapoor so basically I have a json file which contains all the available api urls. in each of the services i build I first need to get the url from the data_urls.json and then use that url to produce an httpget result. in this case it would be the emails._list.json – Sandra Willford Dec 03 '17 at 18:38
  • Ok got it. So what do you want from the emailsAPI method? I mean you got the email URL from data_url.json . Now you just want to get the result from this email_url.json right? – Ankit Kapoor Dec 03 '17 at 18:43
  • yes that's it exactly. – Sandra Willford Dec 03 '17 at 18:44

3 Answers3

1

That's because you're calling async method subscribe and then trying to log the coming value before subscription is resolved. Put last two statements (console.log and return) inside the curly braces just after assigning this.results.emails to the url variable

Mateusz Witkowski
  • 1,646
  • 10
  • 24
1
emailsAPI(): Observable<any> {
    let url: any  
    return this.apiUrlsService.urlsAPI()
        .flatMap(data => {
            this.results = data
            url = this.results.emails
            // you can now access url variable
            return this.http.get('assets/api/email_list.json')
        });

}
SALEH
  • 1,552
  • 1
  • 13
  • 22
  • where do I import flatMap from? import 'rxjs/add/operator/flatMap'; does not seem to do the trick? – Sandra Willford Dec 03 '17 at 17:47
  • 1
    @SandraWillford `import 'rxjs/add/operator/mergeMap';` mergeMap is an alias for flatMap – LLai Dec 03 '17 at 17:52
  • i did this and get this error: ERROR in src/app/components/emails/emails.component.ts(19,37): error TS2339: Property 'subscribe' does not exist on type 'void'. – Sandra Willford Dec 03 '17 at 18:07
  • where are you using `subscribe` ? – SALEH Dec 03 '17 at 18:12
  • in my component where I pass use this method in: 'this.getEmailsService.emailsAPI().subscribe( data => { this.results = data this.emails = this.results } );' – Sandra Willford Dec 03 '17 at 18:18
  • that's because you are not returning anything from `emailsAPI` method. return the `observable` instance as per my edited answer. – SALEH Dec 03 '17 at 18:34
0

As per reactive programming, this is the expected behaviour you are getting. As subscribe method is async due to which you are getting result later on when data is received. But your console log is called in sync thread so it called as soon as you are defining subscribe method. If you want the console to get printed. Put it inside your subscribe data block.

UPDATE:

As per your requirement, you should return Subject instead of Observable as Subject being data consumer as well as data producer. So it will consume data from httpget request from email and act as a producer in the method from where you called emailsAPI method.

emailsAPI(): Subject<any> {
    let emailSubject:Subject = new Subject();  
    this.apiUrlsService.urlsAPI()
        .flatMap(data => {
            this.results = data
            return this.results.emails;
        }).
        subscribe(url=> {
        this.http.get(your_email_url_from_url_received).subscribe(emailSubject);   
   });
    return emailSubject;
}

The subject can be subscribed same as you will be doing with Observable in your calee method.

Ankit Kapoor
  • 1,615
  • 12
  • 18