Observable 구독이있는 함수에서 값을 반환하는 방법은 무엇입니까?


98

Observable이있는 함수에 의해 반환되도록 Observable에서 값을 추출하는 방법을 모르겠습니다. 반환 할 값만 있으면됩니다.

작동하는 현재 버전

function getValueFromObservable() {
    this.store.subscribe(
        (data:any) => {
            console.log(data)
        }
    )
}
getValueFromObservable()

이 기능이 작동하고 값을 반환하는 기능이 필요합니다.

function getValueFromObservable() {
    this.store.subscribe(
        (data:any) => {
            return data
        }
    )
}
console.log(getValueFromObservable())

내가 여기서 뭘 잘못하고 있니?


2
Observable / Promise를 반환하고 Observable이 해결되면이를 통해 데이터를 전달해야합니다
galvan

2
이것에 대한 간단한 코드를 넣을 수 있습니까?
Teddy

6
달성하려는 것은 안티 패턴입니다. 비동기 작업을 "동기화"하려고합니다. Observable이 작동하는 방식이 아닙니다. 요컨대, 대부분의 경우 입력으로 Observable을 갖는 함수는 Observable도 반환해야합니다. 그렇지 않으면 아무것도 반환하지 않습니다. 출력으로 무언가를해야 할 때 구독하세요. 이 경우 당신은 단지 내부에 그것을 할 데이터를 CONSOLE.LOG하려는 경우subscribe
캔 응우 엔

1
나는 당신이 말한 모든 것을 이해합니다. 콘솔 로그를 데모로 사용하고 있으며 해당 데이터를 더 사용할 것이므로 관찰 대상 외부에서 콘솔 로그가 필요합니다. 요점은 옵저버 블을 구독하고, 데이터를 얻고, 구독을 취소하고, 해당 함수에서 데이터를 반환 할 수있는 기능을 가지므로 해당 데이터를 더 사용할 수 있습니다. 안티 패턴이라는 것을 알고 있지만 작동하려면 필요합니다. 도움을 주시면 감사하겠습니다. 현재 내 솔루션은 작동하지만 그것에 대해 너무 확신하지 않습니다.
Teddy

4
주의하십시오! '솔루션'섹션의 코드가 완전히 잘못되었습니다. 그것을 사용하지 마십시오! this.store.subscribe ((data : any) => {output = data}) .unsubscribe () 섹션이 반환 될 때까지 완료되는 경우에만 작동합니다. 그렇지 않으면 undefined를 반환합니다.
Rodion Golovushkin

답변:


58

편집 : RXJS의 최신 버전에서 파이프가 작동하는 방식에 대한 변경 사항을 반영하기 위해 코드를 업데이트했습니다. 이제 모든 연산자 (예제 참조)가 pipe () 연산자로 래핑됩니다.

나는이 질문이 꽤 오래 전이고 당신은 확실히 적절한 해결책을 가지고 있음을 알고 있지만 이것을 찾는 사람에게는 비동기 패턴을 유지하겠다는 약속으로 해결하는 것이 좋습니다.

더 자세한 버전은 새로운 Promise를 만드는 것입니다.

function getValueFromObservable() {
    return new Promise(resolve=>{
        this.store.pipe(
           take(1) //useful if you need the data once and don't want to manually cancel the subscription again
         )
         .subscribe(
            (data:any) => {
                console.log(data);
                resolve(data);
         })
    })
}

받는 쪽에서 다음과 같이 해결하겠다는 약속을 "대기"하게됩니다.

getValueFromObservable()
   .then((data:any)=>{
   //... continue with anything depending on "data" after the Promise has resolved
})

더 얇은 솔루션은 대신 RxJS의 .toPromise ()를 사용하는 것입니다.

function getValueFromObservable() {
    return this.store.pipe(take(1))
       .toPromise()   
}

수신 측은 물론 위와 동일하게 유지됩니다.


getValueFromObservable함수 의 반환 유형은 무엇입니까 ?
hardywang

상점 데이터의 유형에 관계없이 약속이어야합니다. 예 : Promise <StoreType>
jparg

4
해결해야 할 약속을 반환하고 직접 값을 반환하지 않습니다.
Roj

1
속성 'take'가 'Observable <>'유형에 존재하지 않습니다
Memmo

1
@Memmo 대신 .pipe (take (1)) 시도
Thibault

20

이것은 사용에 대한 정확한 아이디어가 아닙니다. Observable

컴포넌트에서 객체 (컴포넌트에서 사용할 것)를 보유 할 클래스 멤버를 선언해야합니다.

export class MyComponent {
  name: string = "";
}

그러면 a Service가 다음을 반환합니다 Observable.

getValueFromObservable():Observable<string> {
    return this.store.map(res => res.json());
}

Component 그것에서 값을 검색 할 수 있도록 준비해야합니다.

OnInit(){
  this.yourServiceName.getValueFromObservable()
    .subscribe(res => this.name = res.name)
}

의 값을 Observable변수 에 할당해야 합니다.

그리고 템플릿은 변수를 소비합니다 name.

<div> {{ name }} </div>

사용하는 또 다른 방법 Observable을 통해서이다 async파이프 http://briantroncone.com/?p=623

참고 : 요청한 내용이 아닌 경우 자세한 내용으로 질문을 업데이트하세요.


글쎄요. 문제는 데이터가 옵저버 블 내부에서 캡처되고 콘솔 로그 만 가능하다는 것입니다. 그 값과 console.log 또는 그것이 상주하는 함수를 호출하여 다른 파일에서 무엇이든 반환하고 싶습니다.
Teddy

Andrei는 name콜백을 구성 요소의 name변수 에 할당하여 콜백 외부 에서 사용 가능 하게 만드는 방법을 지적했습니다 . name귀하의 경우 동기식 으로 반환 할 수 없습니다 .
Matt

@ 매트 : 나는 그것을 사용할 수 없습니다 Oninit어떤 것은 내가 다음과 같이 명시 적으로 내 호출 코드 외모를 반환해야 할 경우, 같은 this.actions$.ofType(SearchActions.SEARCH_MULTIPLE_NEW_QUERY).map(toPayload).fnWithMultipleAsyncReturns()
ishandutta2007

@ ishandutta2007 안녕하세요. 문제에 관한 새로운 질문을 만드는 것이 좋습니다.
Matt

@ 매트 : 경우에 당신이보고 싶을 생성 ( stackoverflow.com/questions/43381922/... )
ishandutta2007

7

반환 될 동일한 Observable을 미리 구독하려면 다음을 사용하십시오.

.하다():

function getValueFromObservable() {
    return this.store.do(
        (data:any) => {
            console.log("Line 1: " +data);
        }
    );
}

getValueFromObservable().subscribe(
        (data:any) => {
            console.log("Line 2: " +data)
        }
    );

3
같은 당신은 또한 다른 연산자를 사용할 수 있습니다 .map(data => data)같은 일을하고 결과를 기대하는 곳마다 다음을 구독하는
ashok_khuman

나는 ashok_khuman에 동의합니다. 여기 angular.io/guide/pipes
Armando Perea

이것은 좋은 대답이 될 수 있지만 사실 그것에 대해 아무것도 설명하지 않았기 때문에 나쁜 대답으로 만듭니다. "사전 구독"이란 무엇을 의미합니까? 그리고 스레드 오프너의 질문을 해결해야합니까?
Florian Leitgeb

RxJS 6 do에서는 이제 호출 tap되며 파이프에서 사용해야합니다. 또한주의 tap와 같은 다른 처리기에 대한 여러 매개 변수를 next, complete하고 error.
Simon_Weaver

7

문제는 데이터가 옵저버 블 내부에서 캡처되고 콘솔 로그 만 가능하다는 것입니다. 그 값과 console.log 또는 그것이 상주하는 함수를 호출하여 다른 파일에서 무엇이든 반환하고 싶습니다.

옵저버 블 내부에서 "현재 값"getter를 찾고있는 것 같습니다.

Subject그리고 Observable그런 일이 없습니다. 값이 방출되면 구독자에게 전달되고 값 Observable이 완료됩니다.

BehaviorSubject마지막으로 방출 된 값을 저장하고 새 구독자에게 즉시 방출하는 것을 사용할 수 있습니다 .

또한 getValue()현재 값을 가져 오는 방법 도 있습니다 .

추가 자료 :

RxJS 동작 주제

RxJS Subject 또는 Observable의 현재 값을 얻는 방법은 무엇입니까?


2

관찰 가능한 값은 모든 위치에서 검색 할 수 있습니다. 소스 시퀀스는 먼저 다른 곳에서 방출 할 수 있는 특수 관찰자에게 푸시 됩니다. 이는 RxJS (Reactive Extensions) 의 주제 클래스 를 통해 수행됩니다.

var subject = new Rx.AsyncSubject();  // store-last-value method

관찰자에게 값을 저장합니다 .

subject.next(value); // store value
subject.complete(); // publish only when sequence is completed

다른 곳에서 값을 검색하려면 다음과 같이 관찰자를 구독하십시오.

subject.subscribe({
  next: (response) => {
      //do stuff. The property name "response" references the value
  }
});

주제는 Observable과 Observer입니다. 다른 사용 시나리오에 대한 BehaviourSubject 및 ReplaySubject와 같은 다른 주제 유형이 있습니다.

RxJS를 가져 오는 것을 잊지 마십시오.

var Rx = require('rxjs');

1

이전 답변이 패션으로 작동 할 수 있지만 계속해서 Observable을 사용하려면 BehaviorSubject를 사용하는 것이 올바른 방법이라고 생각합니다.

예:

    this.store.subscribe(
        (data:any) => {
            myService.myBehaviorSubject.next(data)
        }
    )

서비스에서 :

let myBehaviorSubject = new BehaviorSubjet(value);

component.ts에서 :

this.myService.myBehaviorSubject.subscribe(data => this.myData = data)

이게 도움이 되길 바란다!


0

예를 들어 이것은 내 html 템플릿입니다.

<select class="custom-select d-block w-100" id="genre" name="genre"
                  [(ngModel)]="film.genre"
                  #genreInput="ngModel"
                  required>
            <option value="">Choose...</option>
            <option *ngFor="let genre of genres;" [value]="genre.value">{{genre.name}}</option>
          </select>

이것은 내 구성 요소의 템플릿으로 바인딩 된 필드입니다.

  // Genres of films like action or drama that will populate dropdown list.
  genres: Genre[];

서버에서 영화 장르를 동적으로 가져옵니다. 내가 만든 서버와 통신하려면FilmService

이것은 서버와 통신하는 방법입니다.

 fetchGenres(): Observable<Genre[]> {
    return this.client.get(WebUtils.RESOURCE_HOST_API + 'film' + '/genre') as Observable<Genre[]>;
  }

이 메서드가 Observable<Genre[]>다음과 같은 것을 반환 하지 않는 이유는 무엇 Genre[]입니까?

JavaScript는 async값 비싼 프로세스 후 메서드가 값을 반환 할 때까지 기다리지 않습니다. 비싸다는 것은 가치를 반환하는 데 시간이 걸리는 프로세스를 의미합니다. 서버에서 데이터를 가져 오는 것과 같습니다. 따라서 Observable의 참조 반환하고 구독해야합니다.

예를 들어 내 구성 요소에서 :

ngOnInit() {
    this.filmService.fetchGenres().subscribe(
      val => this.genres = val
    );
  }

0
function getValueFromObservable() {
    this.store.subscribe(
        (data:any) => {
            return data
        }
    )
}
console.log(getValueFromObservable())

위의 경우 console.log는 promise가 해결되기 전에 실행되므로 값이 표시되지 않으면 다음과 같이 변경하십시오.

function getValueFromObservable() {
    return this.store
}

getValueFromObservable()
 .subscribe((data: any) => {
    // do something here with data
    console.log(data);
});

다른 해결책은 getValueFromObservable 내부의 데이터가 필요할 때 연산자를 사용하여 관찰 가능한 값을 반환하고 함수를 구독하는 것입니다.

 function getValueFromObservable() {
        return this.store.subscribe((data: any) => {
            // do something with data here
            console.log(data);
            //return again observable.
            return of(data);
       })
    }

    getValueFromObservable()
     .subscribe((data: any) => {
        // do something here with data
        console.log(data);
    });

0

단일 스레드, 비동기, 약속 지향, 반응 추세의 자바 스크립트 세계 async/await에서 명령형 프로그래머의 가장 친한 친구는 다음과 같습니다.

(async()=>{

    const store = of("someValue");
    function getValueFromObservable () {
        return store.toPromise();
    }
    console.log(await getValueFromObservable())

})();

store여러 값의 시퀀스 인 경우 :

  const aiFrom = require('ix/asynciterable').from;
  (async function() {

     const store = from(["someValue","someOtherValue"]);
     function getValuesFromObservable () {
        return aiFrom(store);
     }
     for await (let num of getValuesFromObservable()) {
       console.log(num);
     }
  })();

데이터 배열의 경우 왜 비동기 성을 사용합니까?
Janos Vinceller

@JanosVinceller 이것은 코드의 다른 부분에 초점을 맞춘 예제 일뿐입니다. from(["someValue","someOtherValue"])둘 이상의 값을 방출하는 옵저버 블로 대체 할 수 있습니다 . 을 사용하는 것이 더 적합 할 것 같습니다 interval(1000).
Marinos An

0

적절한 방법은 observable을 함수에서 반환하고 필요할 때마다 구독하는 것입니다. observable은 게으 르기 때문에 구독 할 때만 값을 방출하기 시작합니다.

여기에 제가 처음에 가지고 놀던 흥미로운 이벤트 중심 솔루션이 하나 더 있습니다. 다음 예제는 nodejs의 " events "모듈을 사용하여 이를 수행합니다. 유사한 모듈이있는 다른 프레임 워크와 함께 사용할 수 있습니다. ( 참고 : 사용되는 모듈에 따라 구문 및 스타일이 변경 될 수 있습니다.)

var from =require("rxjs").from;
var map = require("rxjs/operators").map;
var EventEmitter = require("events");

function process(event) {
    from([1,2,3]).pipe(
        map(val => `The number is:: ${val}`)
    ).subscribe((data) => {
       event.emit("Event1", data); //emit value received in subscribe to the "Event1" listener
    });
}

function main() {
   class Emitter extends EventEmitter{};
    var event = new Emitter(); //creating an event
    event.on("Event1", (data)=>{ //listening to the event of name "Event1" and callback to log returned result
        console.log(data); //here log, print, play with the data you receive
    });
    process(event); //pass the event to the function which returns observable.
}

main(); //invoke main function

방출과 청취의 방법으로 서로 다른 장소에서 데이터를 전달할 수있는 아이디어를 보여주는 예일뿐입니다. 이벤트 구동 코드라고도합니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.