2017-10-11 5 views
2

J'utilise AngularFire2 et je fais quelque chose comme ceci:Existe-t-il un équivalent flatMap qui renvoie l'observable interne?

// assume loggedInUserId is Observable<string> 
var firebaseList = loggedInUserId 
    .flatMap((userId) => this.db.list(this.firebaseRoot.child(userId))) 

this.db.list retourne un FirebaseListObservable<any[]> avec des fonctions pratiques comme push, delete, etc., mais flatMap ne retourne que Observable<any[]> donc je ne suis pas accès à leur.

Existe-t-il un équivalent à flatMap qui renvoie le FirebaseListObservable? Ou est-ce impossible?

+0

C'est impossible. Voir mes commentaires dans [ce] (https://github.com/angular/angularfire2/issues/1008#issuecomment-304510732) AngularFire2 question pour une explication. N'hésitez pas à adapter les commentaires et [self-answer] (https://stackoverflow.com/help/self-answer) à votre question. – cartant

Répondre

0

Vous pouvez essayer carte d'utilisation à la place, il va conserver l'observable d'origine de firebase

Modifié: peut-être casting est la réponse

var firebaseList = loggedInUserId.flatMap((userId) => 
this.db.list(this.firebaseRoot.child(userId))) as FirebaseListObservable<any> 
firebaseList.flatMap(items=>ob.push({foo:'bar'})).subscribe() 

Pour le changement à droite en tapant s'il vous plaît voir ce How do I use .take on FirebaseListObservable?

+0

C'est vrai, mais j'ai un 'Observable' de' Observable's, ce qui signifie que je dois faire 'x | async | async' et toutes sortes d'autres bizarreries. Je vais regarder dans ce lien si - je pourrais être en mesure de le lancer avec "as" ... –

+0

Ya vous avez raison, peut-être cast et l'aplatir avec flatmap va travailler –

+1

Je ne crains pas:/casting avec 'comme 'et la connexion à la console entraîne toujours un' Observable'. –

0

Est-ce que cela aide?

loggedInUserId.subscribe(userId => { 
    var firebaseList = this.db.list(this.firebaseRoot.child(userId)) 
    // do stuff with the list 
} 

Modifier

Est-ce que switchMap retourne le type dont vous avez besoin?

const firebaseList = 
    loggedInUserId.switchMap(userId => 
    this.db.list(this.firebaseRoot.child(userId)) 
) 
+0

Ouais j'ai regardé cette approche, mais j'ai des méthodes de classe qui utilisent les fonctions Firebase, et je préfère les garder simples et synchrones plutôt que d'utiliser 'subscribe' à chaque fois. –

+0

Donc, la suggestion de Fan d'utiliser 'map()' (où j'ai utilisé subscribe) devrait le faire. Je comprends que le motif 'return OuterObservable.someOperator (outerVal => {return InnerObservable ...})' retournera le type de l'interne. Vous avez à peu près cela, alors peut-être que l'opérateur est incorrect. Je vais vérifier la théorie. –

+0

Pas de chance sur switchMap - Le code VS me dit que c'est le test '(var local): Observable '. Je pense que le commentaire de @ cartant pourrait être la réponse. –

0

Vous pouvez créer un convertisseur

const mapToFirebaseListObservable = (source) => { 
    new FirebaseListObservable(observer => { 
    return source.subscribe({ 
     next(x) { observer.next(x); }, 
     error(err) { observer.error(err); }, 
     complete() { observer.complete(); } 
    }) 
    }) 
} 

Utilisez-le avec

var firebaseList = mapToFirebaseListObservable(
    loggedInUserId 
    .flatMap((userId) => this.db.list(this.firebaseRoot.child(userId))) 
) 

Je ne l'ai pas essayé sur une firebase installation complète, de sorte que vous pouvez obtenir un newing d'erreur up FirebaseListObservable, mais je l'ai essayé avec un Observable avec une fonction ajoutée

const newObservable = new Observable(observer => { 
    ... 
}) 
newObservable['myFn'] =() => 'from myFn' 

et la fonction est présente et appelable sur la sortie.

EDIT: Cela semble également travailler

const toInner = (source) => { 
    return source.operator && source.operator.project 
    ? source.operator.project() 
    : source 
} 

Utilisation:

var firebaseList = toInner(
    loggedInUserId 
    .flatMap((userId) => this.db.list(this.firebaseRoot.child(userId))) 
) 

Il pourrait également être transformé en un opérateur enchaîné

const toInner = function() { 
    const source = this 
    return source.operator && source.operator.project 
    ? source.operator.project() 
    : source 
} 
Observable.prototype.toInner = toInner; 

Voir aussi here pour Rxjs v5.50beta sur les modifications apportées à la création d'opérateurs .