Comment synchroniser Angular2 http get?
je comprends l'utilisation de observable je peux exécuter une méthode lorsque la requête est terminée, mais comment puis-je attendre qu'un http soit terminé et retourner la réponse en utilisant le http ng2?
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;
}
la" valeur " sera nulle quand elle sera retournée car get est async..
8 réponses
vous ne devriez pas essayer de faire en sorte que les appels http se comportent de façon synchrone. Jamais une bonne idée.
pour votre getAllUser
mise en oeuvre il devrait retourner un observable de la fonction et le code appelant devrait s'abonner au lieu de vous créer un abonnement à l'intérieur de la méthode elle-même.
quelque Chose comme
getAllUser(): Observable<UserDTO> {
return this.http.get("MY_URL")
.map(res => res.json());
}
dans votre code d'appel, vous devez vous abonner et faire ce que vous voulez.
votre classe de service:/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();
});
}
}
votre composante: /projet/app/composants/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
}
}
en regardant la source angulaire(https://github.com/angular/angular/blob/master/packages/http/src/backends/xhr_backend.ts#L46), il est évident que L'attribut async de XMLHttpRequest n'est pas utilisé. Le troisième paramètre de XMLHttpRequest doit être défini à "false" pour les requêtes synchrones.
s'il vous plaît trouver le code pour votre problème Vous trouverez ci-dessous le fichier de composants et de services.Et le Code fonctionne bien pour 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!")
);
}
}
ci-dessous est le fichier de service..
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;
}
}
}
une autre solution serait de mettre en place une file d'attente prioritaire de sorte.
D'après ce que j'ai compris, les requêtes http ne sont pas exécutées tant que vous n'ajoutez pas d'abonnés. Par conséquent, vous pouvez faire quelque chose comme ceci:
Observable<Response> observable = http.get("/api/path", new RequestOptions({}));
requestPriorityQueue.add(HttpPriorityQueue.PRIORITY_HIGHEST, observable,
successResponse => { /* Handle code */ },
errorResponse => { /* Handle error */ });
Cela suppose que requestPriorityQueue
est un service injecté dans votre composant. La file d'attente prioritaire stockerait les entrées dans un tableau dans le format suivant:
Array<{
observable: Observable<Response>,
successCallback: Function,
errorCallback: Function
}>
vous devez décider comment les éléments sont ajoutés à votre tableau. Enfin, l' voici ce qui se passera en arrière-plan:
// HttpPriorityQueue#processQueue() called at a set interval to automatically process queue entries
processQueue
méthode serait de faire quelque chose comme ceci:
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);
});
}
Si vous êtes en mesure d'ajouter de nouvelles dépendances vous pouvez essayer d'utiliser d'MNP package: asynchrone de priorité de la file d'attente
j'ai regardé et je n'ai pas pu trouver le moyen de faire une synchronisation D'appel HTTP au lieu d'async.
donc le seul moyen de contourner cela: envelopper votre appel dans une boucle de temps avec un drapeau. Ne laissez pas le code continuer jusqu'à ce que ce drapeau ait la valeur "continue".
Pseudo code comme suit:
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');
}
comme vous le voyez, premier rappel en attente d'une donnée de request et là vous pouvez continuer avec votre logique (ou utiliser la troisième)
exemple:
.. subscribe( data => {
this.value = data;
doSomeOperation;
},
error => console.log(error),
() => {console.log("Completed");
or do operations here..;
}
});
Comment utiliser $.ajax (de jQuery) ou XMLHttpRequest.
Il peut utiliser comme asynchornize.