128 votes

Comment retourner la valeur d'une fonction qui contient un abonnement à un Observable ?

Je ne sais pas comment extraire la valeur d'un Observable qui sera retournée par une fonction dans laquelle l'Observable est présent. J'ai juste besoin d'une valeur à retourner, rien d'autre.

Version actuelle qui fonctionne

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

J'ai besoin que ça fonctionne, que la fonction renvoie une valeur, puis.. :

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

Qu'est-ce que je fais de mal ici ?

2 votes

Vous devez renvoyer un Observable/Promesse et transmettre les données par son intermédiaire lorsque votre observable est résolu.

2 votes

Pouvez-vous mettre un code simple pour cela ?

8 votes

Ce que vous essayez de faire est un anti-modèle : Vous essayez de "synchroniser" une tâche asynchrone. Ce n'est pas la façon dont les observables sont censés fonctionner. En bref, dans la plupart des cas, une fonction ayant un observable en entrée doit également retourner un observable - ou ne rien retourner. Et lorsque vous avez besoin de faire quelque chose avec la sortie, abonnez-vous à celle-ci. Dans ce cas, si vous voulez consigner les données dans console.log, il suffit de le faire à l'intérieur de subscribe

71voto

jparg Points 350

Je me rends compte que cette question date d'il y a un certain temps et que vous avez sûrement déjà trouvé une solution appropriée, mais pour tous ceux qui recherchent cette solution, je suggère de la résoudre avec une Promise pour conserver le modèle asynchrone. Une version plus verbeuse serait de créer une nouvelle Promise :

function getValueFromObservable() {
    return new Promise(resolve=>{
        this.store
         .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);
         })
    }
}

À l'extrémité réceptrice, vous devrez ensuite "attendre" la résolution de la promesse avec quelque chose comme ceci :

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

Une solution plus légère consisterait à utiliser .toPromise() de RxJS à la place :

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

Le côté réception reste le même que ci-dessus, bien sûr. J'espère que cela vous aidera !

0 votes

Quel est le type de retour de votre getValueFromObservable fonction ?

0 votes

Devrait être une promesse avec le type de données du magasin, par exemple Promise<StoreType>.

0 votes

C'est une approche intéressante : utiliser la fonctionnalité de compatibilité ascendante pour rendre le code compatible avec vos connaissances actuelles, même pour un nouveau code. Je pense qu'il a probablement appris l'utilisation des Observables depuis ce post, ce qui serait préférable.

26voto

Andrei Zhytkevich Points 5310

Ce n'est pas exactement l'idée correcte d'utiliser Observable

Dans le composant, vous devez déclarer un membre de la classe qui contiendra un objet (quelque chose que vous allez utiliser dans votre composant).

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

Alors un Service vous renverra un Observable :

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

Component doit se préparer à récupérer une valeur :

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

Vous devez attribuer une valeur à partir d'un Observable à une variable :

Et votre modèle consommera une variable name :

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

Une autre façon d'utiliser Observable est par async tuyau http://briantroncone.com/?p=623

Note : Si ce n'est pas ce que vous demandez, veuillez mettre à jour votre question avec plus de détails.

0 votes

Eh bien, pas tout à fait. Le problème est que les données sont capturées à l'intérieur de l'observable et que je peux simplement les consigner dans le journal de la console. Je veux retourner cette valeur et console.log ou autre à partir d'un fichier différent en appelant la fonction dans laquelle il réside.

0 votes

Andrei a indiqué comment faire le name disponible en dehors de la fonction de rappel en l'affectant à l'élément name variable. Il n'est pas possible de renvoyer name de manière synchrone dans votre cas.

0 votes

Je ne peux pas l'utiliser dans Oninit comme ça, Et si je dois retourner explicitement, Mon code d'appel ressemble à ça this.actions$.ofType(SearchActions.SEARCH_MULTIPLE_NEW_QUERY‌​).map(toPayload).fnW‌​ithMultipleAsyncRetu‌​rns()

7voto

Dudi Points 2180

Si vous souhaitez vous préinscrire au même Observable que celui qui sera renvoyé, utilisez simplement

.do() :

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

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

3 votes

Vous pouvez également utiliser d'autres opérateurs comme .map(data => data) qui fait la même chose, puis l'abonner là où vous attendez le résultat.

0 votes

Je suis d'accord avec ashok_khuman. Voici le guide angular.io/guide/pipes

1 votes

Cela pourrait être une bonne réponse, mais le fait que vous n'ayez rien expliqué à ce sujet en fait une mauvaise réponse. Que signifie "préinscription" ? Et cela devrait-il résoudre la question de l'ouverture du fil ?

7voto

A. Alencar Points 73

Le problème est que les données sont capturées à l'intérieur de l'observable et que je peux simplement les consigner dans la console. Je veux retourner cette valeur et console.log ou autre à partir d'un fichier différent en appelant la fonction dans laquelle elle réside.

On dirait que vous cherchez un getter "current value" à l'intérieur d'un observable, quand il émet et après une émission.

Subject et Observable n'a pas une telle chose. Lorsqu'une valeur est émise, elle est transmise à ses abonnés et la balise Observable en a fini avec elle.

Vous pouvez utiliser BehaviorSubject qui stocke la dernière valeur émise et l'émet immédiatement aux nouveaux abonnés.

Il dispose également d'un getValue() pour obtenir la valeur actuelle ;

Pour en savoir plus :

RxJS BehaviorSubject

Comment obtenir la valeur actuelle d'un sujet ou d'un observable RxJS ?

2voto

Dale Leung Points 126

Les valeurs observables peuvent être récupérées à n'importe quel endroit. La séquence source est d'abord poussé sur une observateur qui est capable d'émettre ailleurs. Pour ce faire, on utilise le Classe de sujet des extensions réactives (RxJS).

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

Stocker la valeur sur le observateur .

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

Pour récupérer la valeur d'un autre endroit, abonnez-vous à l'observateur de la manière suivante :

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

Les sujets sont à la fois des Observables et des Observateurs. Il existe d'autres Types de sujets comme BehaviourSubject et ReplaySubject pour d'autres scénarios d'utilisation.

N'oubliez pas d'importer RxJS.

var Rx = require('rxjs');

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X