Javascript 如何同步Angular2 http get?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/33295207/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to synchronise Angular2 http get?
提问by allcommands.io
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?
我理解使用 observable 我可以在请求完成时执行一个方法,但是我怎么能等到 http get 完成并使用 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..
“值”在返回时将为空,因为 get 是异步的..
采纳答案by Chandermani
You should not try to make http calls behave synchronously. Never a good idea.
您不应该尝试使 http 调用同步运行。从来没有一个好主意。
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.
在您的getAllUser
实现中,它应该从函数返回一个可观察对象,并且调用代码应该订阅而不是您在方法本身内部创建订阅。
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.
在您调用代码时,您应该订阅并做任何您想做的事情。
回答by Suresh
By 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.
通过查看角度源(https://github.com/angular/angular/blob/master/packages/http/src/backends/xhr_backend.ts#L46),很明显 XMLHttpRequest 的 async 属性不是习惯。对于同步请求,XMLHttpRequest 的第三个参数需要设置为“false”。
回答by Dharan G
your service class: /project/app/services/sampleservice.ts
您的服务类:/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
您的组件:/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
}
}
回答by Je Suis Alrick
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:
据我了解,在您添加订阅者之前,http 请求不会被执行。因此,您可以执行以下操作:
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:
这假设requestPriorityQueue
是注入到您的组件中的服务。优先级队列将按以下格式将条目存储在数组中:
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:
该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);
});
}
If you are able to add new dependencies you could try using the following NPM package: async-priority-queue
如果您能够添加新的依赖项,您可以尝试使用以下 NPM 包:async-priority-queue
回答by eDriven_Levar
I looked and I couldn't find any way to make an HTTP call sync instead of async.
我看了看,找不到任何方法来使 HTTP 调用同步而不是异步。
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.
所以解决这个问题的唯一方法是:用一个标志将你的调用包装在一个 while 循环中。不要让代码继续,直到该标志具有“继续”值。
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');
}
回答by stackinfostack
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;
}
}
}
回答by Abdusattar Tursunkul
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..;
}
});
回答by harufumi.abe
How about to use $.ajax(of jQuery) or XMLHttpRequest.
如何使用 $.ajax(of jQuery) 或 XMLHttpRequest。
It can use as asynchornize.
它可以用作 asynchornize。