如何在angular中返回一个Observablehttpasync调用的响应?

javascript angular asynchronous typescript observable


我有返回一个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!
  }
}

我检查了如何从异步调用返回响应?发布但找不到解决方案




Answer 1 eko


Reason:

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!
}


Solution:

那么我们如何克服这个问题呢?我们将使用作为 subscribe 方法的回调函数。因为当数据从服务器到达时,它将位于带有响应的 subscribe

所以把代码改成。

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

过了一段时间后,会打印出回应。


您应该做什么:

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

要提到的另一件事是,如果您来自 Promise 后台,则 then 回调对应于带有可观察对象的 subscribe


您不应该做的事情:

你不应该尝试把异步操作改成同步操作(不是说你可以)。我们设置异步操作的原因之一是为了不让用户在等待一个操作完成的同时,还可以在这个时间段内做其他事情。假设你的一个异步操作需要3分钟才能完成,如果我们没有异步操作,界面会冻结3分钟。


建议阅读:

这个答案的原始功劳是:如何从异步调用返回响应?

但是随着angular2的发布,我们被介绍到了类型cript和observables,所以这个答案希望能涵盖用observables处理异步请求的基础知识。




Answer 2 RAVI PATEL


在angularjavascript中进行http调用是异步操作。所以当你进行http调用时,它将指定新的线程来完成这个调用,并与另一个线程开始执行下一行。这就是为什么你会得到未定义的值,所以做下面的修改来解决这个问题。

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



Answer 3 Kliment Ru


如果仅在模板中使用myEvents,则可以使用asyncPype。

这是asyncPype和Angular4 HttpClient的示例https://stackblitz.com/edit/angular-rhioqt?file=app%2Fevent.service.ts




Answer 4 Kooldandy


Observables是懒惰的,所以你必须通过订阅来获取值。你在代码中正确地订阅了它,但同时在'subscribe'块之外记录了输出。这就是为什么它是'未定义'的原因。

ngOnInit() {
  this.es.getEventList()
    .subscribe((response) => {
        this.myEvents = response;
    });

  console.log(this.myEvents); //Outside the subscribe block 'Undefined'
}

所以,如果你把它记录在订阅块中,那么它就会正常记录响应。

ngOnInit(){
  this.es.getEventList()
    .subscribe((response)=>{
        this.myEvents = response;
        console.log(this.myEvents); //Inside the subscribe block 'http response'
    });
}



Answer 5 Suneet Bansal


这是问题所在,您正在将 this.myEvents 初始化为 subscribe() ,而这是在 subscribe() 块之外执行 console.log() 时执行的。因此,在 this.myEvents 初始化之前被调用 console.log()

请将你的 console.log()代码也移到 subscribe()里面,你就完成了。

ngOnInit(){
    this.es.getEventList()
        .subscribe((response)=>{
            this.myEvents = response;
            console.log(this.myEvents);
        });
  }