AngularFirebase cum faceți operația query.once să aștepte până când returnează valoarea?

Folosesc Angular și Firebase pentru aplicația mea web. Apel o funcție a unui serviciu (A-service.ts) de la constructorul unei clase de componente (A-component.ts) pentru a obține un nume de utilizator.

Cod constructor:

constructor(private aService: AService, private firebase: AngularFireDatabase) { 
    this.userName = aService.getUserName(firebase)[0];   }

Cod de serviciu:

var user = [];
    var query = firebase.database.ref("Users").orderByKey();
    query.once("value")
      .then(function (snapshot) {
        snapshot.forEach(function (childSnapshot) {
          var key = childSnapshot.key;
          var childData = childSnapshot.val();
          if (key = localStorage.getItem("LoggedUser")) {
            user.push(childData.Name);
          }
        });
      });
    return user;
  }

Deci problema cu codul este că în cadrul metodei de serviciu, query.once se comportă asincron și, prin urmare, nu pot returna utilizatorul corect la constructor.

Poate cineva să sugereze o soluție la aceeași.?


person Amal    schedule 26.03.2018    source sursă


Răspunsuri (3)


Există un pachet rxjs bun care poate face acest lucru pentru tine. Aruncă o privire la rxjs/toPromise.

https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/topromise.md

Dacă îl importați în fișierul dvs. service sau app.module.ts.

import 'rxjs/add/operator/toPromise';

Apoi primiți o promisiune, în loc de un observabil, dar încă trebuie să gestionați această logică în constructor.

constructor

constructor(private aService: AService, private firebase: AngularFireDatabase) { 
  aService.getUserName(firebase)
    .then(user => {
      this.userName = user;
    });
}

service

return firebase.database().ref('Users')
  .orderByKey()
  .once('value')
  .toPromise()
  .then(snapshot => {
    const user = [];
    snapshot.forEach(childSnapshot => {
      const key = childSnapshot.key;
      const childData = childSnapshot.val();

      if (key = localStorage.getItem('LoggedUser')) {
        user.push(childData.Name);
      }
    });

    if (user.length > 0) {
      return user[0];
    }
  });
person sketchthat    schedule 26.03.2018
comment
Buna Multumesc, am inteles solutia. deoarece folosesc AngularFireDatabase.database() dă o eroare precum Nu se poate invoca o expresie al cărei tip nu are o semnătură de apel. Tipul „Bază de date” nu are semnături de apel compatibile. Acestea permit doar AngularFireDatabase.database(și nu AngularFireDatabase.database()). Dacă folosim baza de date, toPromise nu este o funcție a bazei de date. - person Amal; 27.03.2018

Dacă doriți ca numele de utilizator să se schimbe în direct cu modificările valorilor bazei de date, puteți reveni ca un observabil în sine afișat în html. Pentru mai multe referințe, consultați Top 7 concepte RxJS pentru dezvoltatorii angular.

component.html

<div>{{username | async}}</div>

component.ts

username;
constructor(private aService: AuthService) {
    this.username = aService.getUserName();
}

AuthService.ts

getUserName() {
    return firebase.database().ref('Users').val();
}

Editare: Dacă doriți valoarea numelui de utilizator în component.ts, atunci înlocuiți constructorul cu

username;
subscription;
constructor(private aService: AuthService) {
    this.subscription = aService.getUserName().subscribe((user) => {
        this.username = username;
    });
}
ngOnDestroy(){
    this.subscription.unsubcribe();
}
person Brahma Rishi    schedule 26.03.2018
comment
Buna multumesc. Am nevoie pentru a introduce utilizatorul în component.ts nu în UI. - person Amal; 27.03.2018

In sfarsit am primit-o. Schimb tipul de returnare al metodei la Promise și returnez promisiunea către constructor pentru a obține valoarea.

Vă mulțumesc https://stackoverflow.com/users/1968911/sketchthat pentru că mi-ați oferit o modalitate de abordare.

person Amal    schedule 27.03.2018