2017-03-27 43 views
27

我有一个服务,它返回一个对我的服务器执行http请求并获取数据的observable。我想要使​​用这些数据,但我总是得到undefined。有什么问题?如何从angular2中的Observable/http/async调用返回响应?

服务

@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! 
    } 
} 
+0

这将是一个很好的一点是要强调一个事实,这是不可能改造的台异步操作的synchrnous一。 – n00dl3

+0

@ n00dl3感谢您的提示!我试图在“你不该做什么:”部分解释。随意编辑它。 – echonax

回答

31

原因:

的原因,它的undefined是,你正在异步操作。这意味着需要一些时间才能完成getEventList方法(主要取决于您的网络速度)。

所以让我们来看看http调用。

this.es.getEventList() 

后,你实际上使(“火”)与subscribe您的HTTP请求,你会等待响应。在等待的时候,javascript会执行这段代码下面的行,如果遇到同步赋值/操作,它会立即执行它们。

于是订阅了getEventList()并等待响应,之后

console.log(this.myEvents);

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

它类似于这样:

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

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


解决方案:

那么,我们如何解决这个问题?我们将使用subscribe方法的回调函数。因为当数据从服务器到达时,它将在响应中位于subscribe之内。

因此改变代码:一段时间后

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

将打印响应..。


你应该做的:

可能有很多事情要做的不仅仅是记录它的其他的响应;当数据到达时,您应该在回调(在subscribe函数内)内执行所有这些操作。

另一件要提及的是,如果你来自Promise背景,then回调对应于subscribe与observables。


你不应该做的:

你不应该试图改变一个异步操作同步操作(不是说你可以)。我们进行异步操作的原因之一是不会让用户等待操作完成,而他们可以在该时间段内完成其他操作。假设你的一个异步操作需要3分钟才能完成,如果我们没有异步操作,界面会在3分钟内冻结。


推荐阅读:

原来的信用这个答案去:How do I return the response from an asynchronous call?

但随着angular2释放我们被介绍给打字稿及观测所以这个答案有望覆盖的基础知识用observables处理异步请求。

0

还确保您将响应映射到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;}) 

}

1

使在角/ javascript中的HTTP调用是异步操作。 因此,当你进行http调用时,它会分配新的线程来完成这个调用,并开始执行另一个线程的下一行。 这就是为什么你得到未定义的价值。 所以要低于变化来解决这个

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

你可以简单地尝试这种方法 -

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