20

I understand using observable I can execute a method when the request is completed, but how can i wait till a http get is completed and return the response using in ng2 http?

getAllUser(): Array<UserDTO> {
    this.value = new Array<UserDTO>();
    this.http.get("MY_URL")
                    .map(res => res.json())
                    .subscribe(
                        data => this.value = data,
                        err => console.log(err),
                        () => console.log("Completed")
    );

    return this.value;
} 

the "value" will is null when its returned because get is async..

Navin
  • 684
  • 1
  • 11
  • 24

8 Answers8

3

enter image description hereBy looking at the angular source (https://github.com/angular/angular/blob/master/packages/http/src/backends/xhr_backend.ts#L46), it is apparent that the async attribute of the XMLHttpRequest is not getting used. The third parameter of XMLHttpRequest needs to be set to "false" for synchronous requests.

Razvan Dumitru
  • 11,815
  • 5
  • 34
  • 54
Suresh
  • 505
  • 1
  • 4
  • 14
3

your service class: /project/app/services/sampleservice.ts

    @Injectable()
    export class SampleService {

      constructor(private http: Http) {
      }

      private createAuthorizationHeader() {
         return new Headers({'Authorization': 'Basic ZXBossffDFC++=='});
      }


      getAll(): Observable<any[]> {
        const url='';
        const active = 'status/active';
        const header = { headers: this.createAuthorizationHeader() };
        return this.http.get(url + active, header)
          .map(
            res => {
              return res.json();
            });
      }

    }

your component: /project/app/components/samplecomponent.ts

export class SampleComponent implements OnInit  {


  constructor(private sampleservice: SampleService) {
  }

  ngOnInit() {
   this.dataset();
  }

  dataset(){
    this.sampleservice.getAll().subscribe(
      (res) => {
        // map Your response with model class
        // do Stuff Here or create method 
        this.create(res);
      },
      (err) => { }
    );
  }
  create(data){
   // do Your Stuff Here
  }

}
Dharan Ganesan
  • 433
  • 2
  • 6
  • 23
0

Please find code for your problem Below is component and service file.And Code is Working fine for synchornize

import { Component, OnInit } from '@angular/core';
import { LoginserviceService } from '../loginservice.service';

@Component({
  selector: 'app-login',
  templateUrl: './login.component.html',
  styleUrls: ['./login.component.css']
})
export class LoginComponent implements OnInit {
  model:any={};
  constructor(private service : LoginserviceService) { 
}

ngOnInit() {

}
save() {
   this.service.callService(this.model.userName,this.model.passWord).
   subscribe(
      success => {
        if(success) {
            console.log("login Successfully done----------------------------    -");
            this.model.success = "Login Successfully done";
     }},
    error => console.log("login did not work!")
  );
 }

}

Below is service file..

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { UserData } from './UserData';
import 'rxjs/add/operator/map'
import 'rxjs/add/operator/toPromise'
import {Observable} from 'rxjs/Rx'

@Injectable()
   export class LoginserviceService {
   userData = new UserData('','');   
   constructor(private http:Http) { }

    callService(username:string,passwrod:string):Observable<boolean> {
     var flag : boolean;      
     return (this.http.get('http://localhost:4200/data.json').
       map(response => response.json())).
        map(data => {
          this.userData = data;
          return this.loginAuthentication(username,passwrod);
        });
      }

  loginAuthentication(username:string,passwrod:string):boolean{
     if(username==this.userData.username && passwrod==this.userData.password){
        console.log("Authentication successfully")
        return true;
   }else{
     return false;
   }


  }
}
stackinfostack
  • 650
  • 2
  • 7
  • 12
0

Another solution would be to implement a priority queue of sort.

From what I understand http requests do not get executed until you add subscribers. Therefore, you can do something like this:

Observable<Response> observable = http.get("/api/path", new RequestOptions({}));

requestPriorityQueue.add(HttpPriorityQueue.PRIORITY_HIGHEST, observable,
                 successResponse => { /* Handle code */ }, 
                 errorResponse => { /* Handle error */ });

This assumes that requestPriorityQueue is a service injected into your component. The priority queue would store entries in an array in the following format:

Array<{
    observable: Observable<Response>, 
    successCallback: Function, 
    errorCallback: Function
}>

You would have to decide how the elements are added to your array. Finally, the following will happen in the background:

// HttpPriorityQueue#processQueue() called at a set interval to automatically process queue entries

The processQueue method would do something like this:

protected processQueue() {
    if (this.queueIsBusy()) {
        return;
    }

    let entry: {} = getNextEntry();
    let observable: Observable<Response> = entry.observable;

    this.setQueueToBusy(); // Sets queue to busy and triggers an internal request timeout counter.
    observable.subscribe()
        .map(response => {
            this.setQueueToReady();
            entry.successCallback(response);
        })
        .catch(error => {
            this.setQueueToReady();
            entry.errorCallback(error);
        });
}

If you are able to add new dependencies you could try using the following NPM package: async-priority-queue

Je Suis Alrick
  • 3,404
  • 2
  • 16
  • 23
0

I looked and I couldn't find any way to make an HTTP call sync instead of async.

So the only way around this: wrap your call in a while loop with a flag. Don't let the code continue until that flag has "continue" value.

Pseudo code as follows:

let letsContinue = false;

//Call your Async Function
this.myAsyncFunc().subscribe(data => {
   letsContinue = true;
}; 

while (!letsContinue) {
   console.log('... log flooding.. while we wait..a setimeout might be better');
}
scopchanov
  • 7,966
  • 10
  • 40
  • 68
eDriven_Levar
  • 361
  • 3
  • 10
-3

as you see, first callback waiting for a data from request and there you can go on with your logic (or use the third one)

example:

.. subscribe( data => { 
              this.value = data; 
              doSomeOperation;
              }, 
              error => console.log(error), 
              () => {console.log("Completed");
                      or do operations here..;
                    }
});
-4

How about to use $.ajax(of jQuery) or XMLHttpRequest.

It can use as asynchornize.

harufumi.abe
  • 817
  • 9
  • 8
-10

You should not try to make http calls behave synchronously. Never a good idea.

Coming to your getAllUser implementation it should return an observable from the function and the calling code should subscribe instead of you creating a subscription inside the method itself.

Something like

getAllUser(): Observable<UserDTO> {
        return this.http.get("MY_URL")
                        .map(res => res.json());
} 

In you calling code, you should subscribe and do whatever you want.

Chandermani
  • 42,589
  • 12
  • 85
  • 88
  • 32
    This response offers an alternative implementation to the questions and I appreciate the response. However, this does not answer the question. Is there no way to make a synchronous http request? I am looking for an answer to the same question and I am OK with blocking the browser (in fact I want it to) until I get the response. – inki Apr 12 '16 at 16:45
  • 2
    This answer only suggests not to use sync xhr, it never explains the reason in the question's use case nor even answers the question in any way but only provides an answer to another question. – Downhillski Oct 17 '16 at 19:40
  • By looking at the angular source, it seems the async attribute of the XMLHttpRequest is not getting used. – Suresh Mar 30 '17 at 20:53
  • @inki Making a "sync" request in a browser would freeze the whole browser. That's a horrible user experience. – Targaryen Sep 27 '17 at 19:23
  • @inki See this Google post from Jan 2012 about no longer allowing Synchronous XHRs https://developers.google.com/web/updates/2012/01/Getting-Rid-of-Synchronous-XHRs – Targaryen Sep 27 '17 at 19:31
  • @Targaryen This is a very old question and don't require this anymore, however I never mentioned that my use would be user facing or UI related. – inki Sep 27 '17 at 20:38