1

I have a login component where the user inputs it's e-mail and password. The component sends the fields to the service, where i make a http post request to my nodejs backend to know if the user exists and if password is correct.

The problem is that the response from the server is undefined, but I can get the value of the response from the network of chrome.

I believe the problem is that the request is asynchronous, and so it returns the response before it actually gets the response.

After searching I couldn't find very useful information on how to make the request synchronous.

Here are the codes of my component and of service!

In my component:

login_function(){
    this.token = this.global.check_login(this.login_user,this.login_pass)
        .subscribe(data => this.postData = JSON.stringify(data));
    console.log(this.token);}
}

In the service:

check_login(user, pass) {
    let data = {user:user,password:pass};
    let headers = new Headers({ 'Content-Type': 'application/json' }); 
    let options = new RequestOptions({ headers: headers, method:'post' });

    console.log("user:"+user+"\npass:"+pass);

    return this.http.post(url, {username:user,password:pass}, options)
        .map((response:Response)=> response.json());
  }
Igor
  • 60,821
  • 10
  • 100
  • 175
Luís Costa
  • 23
  • 1
  • 6
  • 1
    check_login is asyncronous, so this.token is undefined. check login is returning an **observable**, so you should **subscribe** to the check_login function and assign the value to `this.token` when the data is available. You are mixing syncronous tasks with asyncronous tasks, which is why `this.token` is undefined when you log it. The solution is NOT to make the requests syncronous, but to (properly) subscribe to the observable, syncronous http requests are not that recommended. Also, url is undefined unless declared somewhere else. – briosheje May 23 '17 at 15:26
  • 3
    Possible duplicate of [How do I return the response from an asynchronous call?](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) – Igor May 23 '17 at 15:30
  • 1
    You should be aware that using synchronous ajax calls is a deprecated as it leads to a bad user experience since *it will freeze the window until it completes*. – megamit May 23 '17 at 15:30
  • @megamit as it is a login page, and in order to allow access to the user to the rest of the application I need to login him – Luís Costa May 23 '17 at 16:02
  • 1
    @LuísCosta - read the marked duplicate. This will give you a solid foundation for working with asynchronous calls in typescript and javascript. You must understand this fundamental concept and how to program using callbacks and promises if you want to write any type of javascript / typescript code that interacts with a server/service. – Igor May 23 '17 at 16:10

1 Answers1

1

You are rightly thinking that it is due to async execution of statements. Change your component code to:

login_function() {
    this.global.check_login(this.login_user, this.login_pass).subscribe(
      data => {
        console.log(data);
      });
 }

Service should be updated to the following code: (Assuming that your server accepts 'user' and 'password' as keys)

check_login(user,pass){
    console.log("user:"+user+"\npass:"+pass);

    let bodyString = JSON.stringify({user:user,password:pass});
    let headers = new Headers({'Content-Type': 'application/json'}); // ... Set content type to JSON
    let options = new RequestOptions({headers: headers}); // Create a request option
    return this.http
     .post(url,bodyString,options)
     .map((response:Response)=> response.json() );

}
Jainam Jhaveri
  • 1,479
  • 1
  • 18
  • 31
  • I assume here that he receives json object as a response – Jainam Jhaveri May 23 '17 at 15:46
  • In the console it prints: {} – Luís Costa May 23 '17 at 15:49
  • what is 'global' variable. It should be an instance of Service injected in your constructor? i.e. constructor(private global: ServiceName){} – Jainam Jhaveri May 23 '17 at 15:51
  • global is the instance of the service! import {GlobalService} from 'app/service/global.service'; constructor(private global:GlobalService){} – Luís Costa May 23 '17 at 15:52
  • and are you using the data variable in the line `let data = {user:user,password:pass};` ? – Jainam Jhaveri May 23 '17 at 15:54
  • I was using that variable at first, but then I wrote the information directly on the request – Luís Costa May 23 '17 at 16:00
  • I changed the component to `this.global.check_login(this.login_user, this.login_pass).subscribe( data => { console.log(data); });` and it prints: "Object {}" when I open it, it has nothing inside – Luís Costa May 23 '17 at 16:01
  • in your service you have used 2 different post requests.. Previously you sent {user: .., password: ...} and now {username: .., password: ...}. What exactly does your server expect? – Jainam Jhaveri May 23 '17 at 16:01
  • There is a possibility that your server code may be incorrect – Jainam Jhaveri May 23 '17 at 16:05
  • The server is expecting a username and a password, and it is returning {"login":"OK"}. I could see that as I saved the request response (in the service) and asked for it later, and I could see it, the problem is that I want the service to communicate with the componnent only when it has the response – Luís Costa May 23 '17 at 16:17
  • `console.log(data);` inside subscribe prints only when it has received the response from the service – Jainam Jhaveri May 23 '17 at 16:20
  • `console.log(data)` prints `Object {}` but when I go to network and open the field response I get `{"login":"OK"}` – Luís Costa May 23 '17 at 16:41
  • this kinda not working for me . can you help me?? @JainamJhaveri – Ravi Jul 25 '19 at 05:31