Как синхронизировать 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());
}
При вызове кода вы должны подписаться и сделать все, что хотите.
Ответ 2
Посмотрев на источник angular https://github.com/angular/angular/blob/master/packages/http/src/backends/xhr_backend.ts#L46), очевидно, что асинхронный атрибут XMLHttpRequest не используется. Третий параметр XMLHttpRequest должен быть установлен на "false" для синхронных запросов.
Ответ 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..;
}
});