如何以角度从可观察/http/异步调用返回响应?

我有一个服务,它返回一个可观察量,它对我的服务器执行http请求并获取数据。我想使用这些数据,但我总是最终得到.怎么了?undefined

服务

@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({...})
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!
  }
}

我选中了如何从异步调用返回响应?帖子,但找不到解决方案


答案 1

原因:

原因是您正在执行异步操作。这意味着完成该方法需要一些时间(主要取决于您的网络速度)。undefinedgetEventList

因此,让我们看一下 http 调用。

this.es.getEventList()

在您实际提出(“解雇”)您的http请求后,您将等待响应。在等待期间,javascript将执行此代码下面的行,如果遇到同步赋值/操作,它将立即执行它们。subscribe

因此,在订阅并等待响应后,getEventList()

console.log(this.myEvents);

行将立即执行。它的值是在响应从服务器到达之前(或者到您首先初始化它的任何东西)。undefined

它类似于执行以下操作:

ngOnInit(){
    setTimeout(()=>{
        this.myEvents = response;
    }, 5000);

    console.log(this.myEvents); //This prints undefined!
}


溶液:

那么,我们如何克服这个问题呢?我们将使用回调函数,即该方法。因为当数据从服务器到达时,它将在响应中。subscribesubscribe

因此,将代码更改为:

this.es.getEventList()
    .subscribe((response)=>{
        this.myEvents = response;
        console.log(this.myEvents); //<-- not undefined anymore
    });

将打印响应。.过了一段时间。


你应该做什么:

除了记录回复之外,可能还有很多事情要做;当数据到达时,您应该在回调内部(函数内部)执行所有这些操作。subscribe

另一件需要提一提的事情是,如果您来自背景,则回调对应于可观察量。Promisethensubscribe


你不应该做什么:

不应尝试将异步操作更改为同步操作(不是可以)。我们执行异步操作的原因之一是,在用户可以在该时间段内执行其他操作时,不要让用户等待操作完成。假设您的一个异步操作需要 3 分钟才能完成,如果我们没有异步操作,接口将冻结 3 分钟。


推荐阅读:

此答案的原始功劳归于:如何从异步调用返回响应?

但是在 angular2 版本中,我们被引入了 typescript 和 observables,所以这个答案有望涵盖使用 observables 处理异步请求的基础知识。


答案 2

在angular/javascript中进行http调用是异步操作。因此,当您进行http调用时,它将分配新线程来完成此调用,并使用另一个线程开始执行下一行。这就是为什么你得到未定义的价值。因此,请进行以下更改以解决此问题

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