2017-03-27 29 views
27

Tôi có dịch vụ trả về một quan sát có yêu cầu http đến máy chủ của tôi và nhận dữ liệu. Tôi muốn sử dụng dữ liệu này nhưng tôi luôn nhận được undefined. Có chuyện gì vậy?Làm cách nào để trả lại phản hồi từ cuộc gọi có thể quan sát/http/async trong angular2?

Dịch vụ:

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

đó sẽ là một điểm tốt để nhấn mạnh trên thực tế nó không phải là có thể chuyển đổi một hoạt động không đồng bộ với một synchrnous-one. – n00dl3

+0

@ n00dl3 Cảm ơn mẹo! Tôi đã cố gắng giải thích trong phần "Những gì bạn không nên làm:". Vui lòng chỉnh sửa nó. – echonax

Trả lời

31

Lý do:

Lý do mà nó undefined là bạn đang làm cho một hoạt động không đồng bộ. Có nghĩa là sẽ mất một chút thời gian để hoàn thành phương thức getEventList (tùy thuộc vào tốc độ mạng của bạn).

Vì vậy, hãy xem cuộc gọi http.

this.es.getEventList() 

Sau khi bạn thực sự làm ("lửa") theo yêu cầu của bạn với http subscribe bạn sẽ có chờ cho các phản ứng. Trong khi chờ đợi, javascript sẽ thực hiện các dòng bên dưới mã này và nếu nó gặp các phép/phép toán đồng bộ, nó sẽ thực thi chúng ngay lập tức.

Vì vậy, sau khi đăng ký vào các getEventList() và chờ đợi câu trả lời,

console.log(this.myEvents);

dòng sẽ được thực hiện ngay lập tức. Và giá trị của nó là undefined trước khi phản hồi đến từ máy chủ (hoặc bất kỳ thứ gì bạn đã khởi tạo nó ngay từ đầu).

Nó tương tự như thực hiện:

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

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


Giải pháp:

Vì vậy, làm thế nào để chúng tôi khắc phục vấn đề này? Chúng tôi sẽ sử dụng chức năng gọi lại là phương pháp subscribe. Bởi vì khi dữ liệu đến từ máy chủ, nó sẽ nằm trong số subscribe với phản hồi.

Vì vậy, thay đổi mã để:

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

sẽ in câu trả lời .. sau một thời gian.


Bạn nên làm gì:

Có thể có rất nhiều thứ để làm với trả lời của bạn khác hơn là chỉ đăng nó; bạn nên thực hiện tất cả các hoạt động này bên trong hàm gọi lại (bên trong hàm subscribe), khi dữ liệu đến.

Một điều nữa cần lưu ý là nếu bạn đến từ nền Promise, cuộc gọi lại then tương ứng với subscribe có thể quan sát được.


gì bạn không nên làm:

Bạn không nên cố gắng thay đổi một hoạt động async đến một hoạt động đồng bộ hóa (không phải là bạn có thể). Một trong những lý do khiến chúng tôi có các hoạt động không đồng bộ là không làm cho người dùng chờ một thao tác hoàn tất trong khi họ có thể thực hiện những việc khác trong khoảng thời gian đó. Giả sử rằng một trong các hoạt động không đồng bộ của bạn mất 3 phút để hoàn thành, nếu chúng tôi không có các hoạt động không đồng bộ, giao diện sẽ đóng băng trong 3 phút.


Reading đề nghị:

Tín dụng gốc để câu trả lời này đi tới: How do I return the response from an asynchronous call?

Nhưng với việc phát hành angular2 chúng tôi đã giới thiệu với nguyên cảo và quan sát nên câu trả lời này hy vọng bao gồm những điều cơ bản của xử lý một yêu cầu không đồng bộ với các quan sát.

0

cũng đảm bảo rằng bạn ánh xạ phản hồi của bạn với đầu ra json. Nếu không, nó sẽ trả về văn bản thuần túy. Bạn làm điều này như thế này:

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

Thực hiện cuộc gọi http trong góc/javascript là hoạt động không đồng bộ. Vì vậy, khi bạn thực hiện cuộc gọi http, nó sẽ gán chuỗi mới để kết thúc cuộc gọi này và bắt đầu thực hiện dòng tiếp theo với một chuỗi khác. Đó là lý do tại sao bạn nhận được giá trị không xác định. do đó hãy chắc bên dưới thay đổi để giải quyết này

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

Bạn chỉ có thể thử phương pháp luận này

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'); 
    } 
Các vấn đề liên quan