简体   繁体   English

如何从 angular 中的 Observable/http/async 调用返回响应?

[英]How do I return the response from an Observable/http/async call in angular?

I have service which returns an observable which does an http request to my server and gets the data.我有一个服务,它返回一个 observable,它向我的服务器发出 http 请求并获取数据。 I want to use this data but I always end up getting undefined .我想使用这些数据,但我总是得到undefined What's the problem?有什么问题?

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发布但找不到解决方案

Reason:原因:

The reason that it's undefined is that you are making an asynchronous operation.undefined的原因是您正在进行异步操作。 Meaning it'll take some time to complete the getEventList method (depending mostly on your network speed).这意味着完成getEventList方法需要一些时间(主要取决于您的网络速度)。

So lets look at the http call.所以让我们看看 http 调用。

this.es.getEventList()

After you actually make ("fire") your http request with subscribe you will be waiting for the response.在您通过subscribe实际发出(“触发”)您的 http 请求后,您将等待响应。 While waiting, javascript will execute the lines below this code and if it encounters synchronous assignments/operations it'll execute them immediately.在等待时,javascript 将执行此代码下方的行,如果遇到同步分配/操作,它将立即执行它们。

So after subscribing to the getEventList() and waiting for the response,所以在订阅了getEventList()并等待响应之后,

console.log(this.myEvents);

line will be executed immediately.行将立即执行。 And the value of it is undefined before 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 subscribe method.我们将使用回调函数,即subscribe方法。 Because when the data arrives from the server it'll be inside the subscribe with the response.因为当数据从服务器到达时,它将在带有响应的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 subscribe function), when the data arrives.当数据到达时,您应该在回调内(在subscribe函数内)执行所有这些操作。

Another thing to mention is that if you come from a Promise background, the then callback corresponds to subscribe with observables.另外要提到的是,如果你来自Promise背景, then回调对应于subscribe with observables。


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 处理异步请求的基础知识。

Making a http call in angular/javascript is asynchronous operation.在 angular/javascript 中进行 http 调用是异步操作。 So when you make http call it will assign new thread to finish this call and start execution next line with another thread.因此,当您进行 http 调用时,它将分配新线程来完成此调用,并在下一行与另一个线程开始执行。 That is why you are getting undefined value.这就是为什么你得到未定义的价值。 so make below change to resolve this所以进行以下更改以解决此问题

this.es.getEventList()  
      .subscribe((response)=>{  
       this.myEvents = response;  
        console.log(this.myEvents); //<-this become synchronous now  
    });

You can use asyncPipe if you use myEvents only in template.如果仅在模板中使用myEvents,则可以使用 asyncPipe。

Here example with asyncPipe and Angular4 HttpClient example这里以 asyncPipe 和 Angular4 HttpClient 为例

Observables are lazy so you have to subscribe to get the value. Observable 是惰性的,因此您必须订阅才能获取值。 You subscribed it properly in your code but simultaneously logged the output outside the 'subscribe' block.您在代码中正确订阅了它,但同时在“订阅”块之外记录了输出。 That's why it is 'undefined'.这就是为什么它是“未定义的”。

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

Here the problem is, you are initializing this.myEvents into subscribe() which is an asynchronous block while you are doing console.log() just out of subscribe() block.这里的问题是,要初始化this.myEventssubscribe()这是一个异步块,而你正在做console.log()刚出来的subscribe()块。 So console.log() getting called before this.myEvents gets initialized.所以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);
        });
  }

The result is undefined because angular process async .结果未定义,因为 angular process async 。 you can trying as below:你可以尝试如下:

async ngOnInit(){
    const res = await this.es.getEventList();
    console.log(JSON.stringify(res));
}

Also make sure that you map your response to a json output.还要确保将响应映射到 json 输出。 Otherwise it will return plain text.否则它将返回纯文本。 You do it this like this:你这样做:

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

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

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

You can use below approach to return values from service您可以使用以下方法从服务返回值

Below is the service:以下是服务:

 export class AppServiceService {
    
      constructor(private http: HttpClient) { }
    
      getStudentDetails(): Observable<Student[]>{
        let headers = new Headers({ 'Content-Type': 'application/json' });
        let options = new RequestOptions({ headers: headers });
        return this.http.get<Student[]>('http://localhost:8080/api/student',options);
    
      }
    
    }

In Component you can use subscribe method to load data as like below在组件中,您可以使用 subscribe 方法来加载数据,如下所示

export class AppComponent {
  
  title = 'angular-demo';

  constructor(private appService: AppServiceService) { }

   studentDetails: Student[];

  ngOnInit(): void {
    this.appService.getStudentDetails().subscribe(data => {
      this.studentDetails=data;
    },error=>{
         console.log(error);
    });

  }
}

For More reference please refer below url:更多参考请参考以下网址:

https://beginnersbug.com/call-http-rest-service-from-angular/ https://beginnersbug.com/call-http-rest-service-from-angular/

To do this you have 2 options:为此,您有 2 个选择:

Suppose we have a service which is returning shipping details array :假设我们有一个返回运输详情数组的服务:

  getShippingPrices(): Observable<IShippingDetails[]> {
    return this.http.get<IShippingDetails[]>('/assets/shipping.json');
  }

1. Use Async pipe : Easy way when you just want to show the result in template 1.使用异步管道:当您只想在模板中显示结果时的简单方法

In the component class directly assign the observable to variable:在组件类中直接将observable赋值给变量:

export class ShippingComponent implements OnInit {
  shipOptions1 = this.cartService.getShippingPrices();
  constructor(private cartService: CartService) {}

  ngOnInit() {}
}

and then use async pipe in template :然后在模板中使用异步管道:

<div *ngFor="let s of shipOptions1 |async">
  <label>{{s.type}}</label>
</div>

Refer: Check the 4th point in this URL https://angular.io/start/start-data#configuring-the-shippingcomponent-to-use-cartservice请参阅:检查此 URL 中的第 4 点https://angular.io/start/start-data#configuring-the-shippingcomponent-to-use-cartservice

2. Use Subscribe : When you want to manipulate it or want do some business logic on/from response 2. 使用 Subscribe :当您想要操作它或想要在响应上/从响应中执行一些业务逻辑时

export class ShippingComponent implements OnInit {
  shipOptions2: IShippingDetails[] = [];
  constructor(private cartService: CartService) {}

  ngOnInit() {
    this.cartService.getShippingPrices().subscribe(response => {
      this.shipOptions2 = response;
      //console.log(this.myEvents);
      //All other code using shipOptions2
    });
  }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Angular 4在可观察对象内部进行http promise调用? - Using Angular 4 how do I make a http promise call inside of an observable? 如何返回异步调用的响应? - How do I return the response from an asynchronous call? 如何将 Angular JS 服务中的变量设置为来自 AngularJS 服务中 $http 调用的响应数据? - How do I set a variable within an Angular JS service to the response data from an $http call within an AngularJS service? 角度ngIf如果可观察到的异步响应 - Angular ngIf observable response with async 如何在Angular 2+中将Observable内部的值作为函数返回 - How do I return the value inside of an Observable as the function in Angular 2+ 如何从 Angular 中的 http/async 调用为接口属性赋值? - How to assign value to interface property from http/async call in Angular? 从标准 for 循环中的异步调用返回响应 - return a response from an async call in a standard for loop 调用成功后,如何从角度2的http调用返回数据 - how to return a data from http call in angular 2 when the call is success 如何在函数内的async.eachSeries循环内从多个get请求返回响应 - How do I return a response from multiple get requests, inside an async.eachSeries loop, inside a function 如何保留Angular 6中可观察到的原始响应? - How to retain the original response from the observable in Angular 6?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM