각도에서 Observable / http / async 호출에서 응답을 반환하는 방법

javascript angular asynchronous typescript observable


내 서버에 http 요청을하는 Observable을 반환하고 데이터를 얻는 서비스가 있습니다. 이 데이터를 사용하고 싶지만 항상 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()

당신은 실제로 ( "불")와 HTTP 요청 한 후 subscribe 하면됩니다 대기 응답을합니다. 기다리는 동안 자바 스크립트는이 코드 아래의 행을 실행하고 동기 할당 / 작업이 발생하면 즉시 실행됩니다.

따라서 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 릴리스에서는 typescript 및 observables가 도입 되었으므로이 답변은 observables로 비동기 요청을 처리하는 기본 사항을 다룹니다.




Answer 2 RAVI PATEL


각도 / 자바 스크립트에서 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


Observable은 게 으르므로 값을 얻으려면 구독해야합니다. 코드에서 올바르게 구독했지만 동시에 '구독'블록 외부에 출력을 기록했습니다. 그것이 '정의되지 않은'이유입니다.

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

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

따라서 subscribe 블록에 로그인하면 응답이 올바르게 기록됩니다.

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() 당신이하고있는 동안 비동기 블록 인 console.log() 그냥의 subscribe() 블록. 따라서 this.myEvents 가 초기화 되기 전에 console.log() 가 호출 됩니다.

subscribe () 내부에서 console.log () 코드를 이동하면 완료됩니다.

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