Javascript 如何从 angular 的 Observable/http/async 调用返回响应?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/43055706/
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 do I return the response from an Observable/http/async call in angular?
提问by eko
I have service which returns an observable which does an http request to my server and gets the data. I want to use this data but I always end up getting undefined. What's the problem?
我有一个服务,它返回一个 observable,它向我的服务器发出 http 请求并获取数据。我想使用这些数据,但我总是得到undefined. 有什么问题?
Service:
服务:
@Injectable()
export class EventService {
constructor(private http: Http) { }
getEventList(): Observable<any>{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get("http://localhost:9999/events/get", options)
.map((res)=> res.json())
.catch((err)=> err)
}
}
Component:
成分:
@Component({...})
export class EventComponent {
myEvents: any;
constructor( private es: EventService ) { }
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
});
console.log(this.myEvents); //This prints undefined!
}
}
I checked How do I return the response from an asynchronous call?post but couldn't find a solution
我检查了如何从异步调用返回响应?发帖但找不到解决办法
回答by eko
Reason:
原因:
The reason that it's undefinedis that you are making an asynchronous operation. Meaning it'll take some time to complete the getEventListmethod (depending mostly on your network speed).
原因undefined是您正在进行异步操作。这意味着完成该getEventList方法需要一些时间(主要取决于您的网络速度)。
So lets look at the http call.
所以让我们看看 http 调用。
this.es.getEventList()
After you actually make ("fire") your http request with subscribeyou will be waitingfor the response. While waiting, javascript will execute the lines below this code and if it encounters synchronous assignments/operations it'll execute them immediately.
在您实际发出(“触发”)您的 http 请求后,subscribe您将等待响应。在等待时,javascript 将执行此代码下方的行,如果遇到同步分配/操作,它将立即执行它们。
So after subscribing to the getEventList()and waiting for the response,
因此,在订阅getEventList()并等待响应后,
console.log(this.myEvents);
console.log(this.myEvents);
line will be executed immediately. And the value of it is undefinedbefore the response arrives from the server (or to whatever that you have initialized it in the first place).
行将立即执行。并且它的值是undefined在响应从服务器(或您首先初始化的任何内容)到达之前。
It is similar to doing:
它类似于:
ngOnInit(){
setTimeout(()=>{
this.myEvents = response;
}, 5000);
console.log(this.myEvents); //This prints undefined!
}
Solution:解决方案:
So how do we overcome this problem? We will use the callback function which is the
subscribemethod. Because when the data arrives from the server it'll be inside thesubscribewith the response.
那么我们如何克服这个问题呢?我们将使用作为
subscribe方法的回调函数。因为当数据从服务器到达时,它会subscribe在响应中。
So changing the code to:
所以把代码改成:
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-- not undefined anymore
});
will print the response.. after some time.
将打印响应......一段时间后。
What you should do:你应该做什么:
There might be lots of things to do with your response other than just logging it; you should do all these operations inside the callback (inside the subscribefunction), when the data arrives.
除了记录它之外,您的回复可能还有很多事情要做;subscribe当数据到达时,您应该在回调中(在函数内部)执行所有这些操作。
Another thing to mention is that if you come from a Promisebackground, the thencallback corresponds to subscribewith observables.
另一件事要提到的是,如果您来自Promise后台,则then回调对应于subscribeobservables。
What you shouldn't do:你不应该做的事情:
You shouldn't try to change an async operation to a sync operation (not that you can). One of the reasons that we have async operations is to not make the user wait for an operation to complete while they can do other things in that time period. Suppose that one of your async operations takes 3 minutes to complete, if we didn't have the async operations the interface would froze for 3 minutes.
您不应该尝试将异步操作更改为同步操作(您不能这样做)。我们有异步操作的原因之一是不要让用户等待操作完成,而他们可以在该时间段内做其他事情。假设您的一项异步操作需要 3 分钟才能完成,如果我们没有异步操作,界面将冻结 3 分钟。
Suggested Reading:
推荐阅读:
The original credit to this answer goes to: How do I return the response from an asynchronous call?
这个答案的原始功劳是:如何从异步调用返回响应?
But with the angular2 release we were introduced to typescript and observables so this answer hopefully covers the basics of handling an asynchronous request with observables.
但是随着 angular2 的发布,我们被引入了 typescript 和 observables,所以这个答案有望涵盖使用 observables 处理异步请求的基础知识。
回答by RAVI PATEL
Making a http call in angular/javascript is asynchronous operation. So when you make http call it will assign new thread to finish this call and start execution next line with another thread. That is why you are getting undefined value. so make below change to resolve this
在 angular/javascript 中进行 http 调用是异步操作。因此,当您进行 http 调用时,它将分配新线程来完成此调用,并在下一行与另一个线程开始执行。这就是为什么你得到未定义的价值。因此进行以下更改以解决此问题
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //<-this become synchronous now
});
回答by Kliment Ru
You can use asyncPypeif you use myEvents only in template.
如果仅在模板中使用myEvents,则可以使用 asyncPype。
Here example with asyncPype and Angular4 HttpClient https://stackblitz.com/edit/angular-rhioqt?file=app%2Fevent.service.ts
这里以 asyncPype 和 Angular4 HttpClient https://stackblitz.com/edit/angular-rhioqt?file=app%2Fevent.service.ts为例
回答by Kooldandy
Observables are lazy so you have to subscribe to get the value. You subscribed it properly in your code but simultaneously logged the output outside the 'subscribe' block. That's why it is 'undefined'.
Observable 是惰性的,因此您必须订阅才能获取值。您在代码中正确订阅了它,但同时在“订阅”块之外记录了输出。这就是为什么它是“未定义的”。
ngOnInit() {
this.es.getEventList()
.subscribe((response) => {
this.myEvents = response;
});
console.log(this.myEvents); //Outside the subscribe block 'Undefined'
}
So if you log it inside the subscribe block then it will log response properly.
因此,如果您将其记录在 subscribe 块中,那么它将正确记录响应。
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents); //Inside the subscribe block 'http response'
});
}
回答by Suneet Bansal
Here the problem is, you are initializing this.myEventsinto subscribe()which is an asynchronous block while you are doing console.log()just out of subscribe()block.
So console.log()getting called before this.myEventsgets initialized.
这里的问题是,要初始化this.myEvents到subscribe()它是一个异步块,而你正在做console.log()只是出于subscribe()块。所以console.log()在this.myEvents初始化之前被调用。
Please move your console.log() code as well inside subscribe() and you are done.
请将您的 console.log() 代码也移动到 subscribe() 中,您就完成了。
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
console.log(this.myEvents);
});
}
回答by NhutLe
The result is undefined because angular process async . you can trying as below:
结果未定义,因为 angular process async 。你可以尝试如下:
async ngOnInit(){
const res = await this.es.getEventList();
console.log(JSON.stringify(res));
}
回答by Hitech Hitesh
Undefined because the value here is logged before any data from the service is set from that above subscribe service call. So you have to wait until the ajax call finishes and set the data from the response data.
未定义,因为此处的值是在从上述订阅服务调用中设置来自服务的任何数据之前记录的。所以你必须等到ajax调用完成并从响应数据中设置数据。
getEventList(): Observable<any>{
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get("http://localhost:9999/events/get", options)
.map((res)=> res.json())
.catch((err)=> err)
}
Here make the Console log inside the subscribe method that will make the log when the data is set in myEvents variable.
这里在 subscribe 方法中创建控制台日志,该方法将在 myEvents 变量中设置数据时创建日志。
ngOnInit(){
this.es.getEventList()
.subscribe((response)=>{
this.myEvents = response;
// This prints the value from the response
console.log(this.myEvents)
});
}
回答by luukgruijs
Also make sure that you map your response to a json output. Otherwise it will return plain text. You do it this like this:
还要确保将响应映射到 json 输出。否则它将返回纯文本。你这样做:
getEventList(): Observable<any> {
let headers = new Headers({ 'Content-Type': 'application/json' });
let options = new RequestOptions({ headers: headers });
return this.http.get("http://localhost:9999/events/get", options)
.map((res)=>{ return res.json();}) <!-- add call to json here
.catch((err)=>{return err;})
}
回答by Harshit
You can simply try this method-
你可以简单地试试这个方法——
let headers = new Headers({'Accept': 'application/json'});
let options = new RequestOptions({headers: headers});
return this.http
.get(this.yourSearchUrlHere, options) // the URL which you have defined
.map((res) => {
res.json(); // using return res.json() will throw error
}
.catch(err) => {
console.error('error');
}

