Как синхронизировать Angular2 http get

Я понимаю, что с помощью наблюдаемого я могу выполнить метод, когда запрос будет завершен, но как я могу дождаться завершения HTTP-получения и вернуть ответ, используя в 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;
} 

"value" будет null, когда возвращается, потому что get is async..

Ответы

Ответ 1

Не следует пытаться заставить синхронно работать с http-вызовами. Никогда не было хорошей идеи.

Приступив к реализации getAllUser, он должен вернуть наблюдаемое из функции, а код вызова должен подписаться, а не создавать подписку внутри самого метода.

Что-то вроде

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

При вызове кода вы должны подписаться и сделать все, что хотите.

Ответ 3

ваш класс обслуживания:/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();
            });
      }

    }

ваш компонент:/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
  }

}

Ответ 4

Введите код вашей проблемы Ниже представлен компонент и служебный файл. И код работает отлично для 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!")
  );
 }

}

Ниже представлен служебный файл.

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;
   }


  }
}

Ответ 5

Другим решением будет реализация очереди приоритетов сортировки.

Из того, что я понимаю, HTTP-запросы не выполняются до тех пор, пока вы не добавите подписчиков. Поэтому вы можете сделать что-то вроде этого:

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

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

Это предполагает, что requestPriorityQueue - это услуга, введенная в ваш компонент. Очередь приоритетов будет хранить записи в массиве в следующем формате:

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

Вам нужно будет решить, как элементы добавляются в ваш массив. Наконец, в фоновом режиме произойдет следующее:

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

Метод processQueue сделает следующее:

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);
        });
}

Если вы можете добавить новые зависимости, вы можете попробовать использовать следующий пакет NPM: async-priority-queue

Ответ 6

Javascript однопоточный, и синхронный HTTP-запрос блокирует весь браузер, пока он ждет ответа. Пожалуйста, рассмотрите другую архитектуру.

Ответ 7

Как использовать $.ajax(из jQuery) или XMLHttpRequest.

Он может использоваться как asynchornize.

Ответ 8

как вы видите, первый обратный вызов ожидает данных от запроса и там вы можете продолжить свою логику (или использовать третью)

Пример:

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