typescript - Angular 2 Firebase Observable para promise não retorna nada
Atualmente, estou trabalhando em um projeto Angular 2 com AngularFire2 e estou tentando converter um FirebaseListObservable para uma Promise. Sei que isso não faz muito sentido, já que Observables são mais úteis, mas essa função fará parte de outra função onde múltiplas promises são encadeadas. E não estou familiarizado com como se inscrever em Observables dentro de uma cadeia de promises... A função é executada no serviço, no entanto, parece não retornar nada. Basicamente, o que eu quero fazer é verificar em uma lista do Firebase se um objeto com um determinado nome já existe e retornar verdadeiro ou falso.
Serviço
constructor(private _af: AngularFire) { }
nameExists(name: string): Promise<boolean> {
return this._af.database.list('users')
.map(users => {
let exists = false;
users.forEach(user => {
if(user.name.toLowerCase() === name.toLowerCase()) {
console.log('Name already exists!');
exists = true;
}
});
return exists;
}).toPromise();
}
componente
constructor(private _usersService: UsersService) { }
check(name) {
this._usersService.nameExists(name)
.then(bool => console.log(bool));
}
Então a função é executada e parece funcionar corretamente, pois imprime no console quando há uma correspondência. No entanto, o console.log() no componente não é executado. Eu acho que a parte do "then" nunca é alcançada. Em outro ponto, existe uma maneira de parar o loop forEach assim que uma correspondência for encontrada?
Qualquer ajuda seria muito apreciada, pois eu não consegui encontrar nenhuma resposta sobre isso.
Resposta #1
O problema é que o operador toPromise converte o observable em uma promise que se resolve com o valor final do observable. Isso significa que o observable deve ser concluído antes que a promise se resolva.
No AngularFire2, observáveis de lista e de objeto não são concluídos; eles são reemitidos sempre que o banco de dados muda.
Você pode resolver o problema usando o operador first, que pega o primeiro valor emitido e então finaliza o observable composto:
import 'rxjs/add/operator/first';
import 'rxjs/add/operator/map';
import 'rxjs/add/operator/toPromise';
...
return this._af.database
.list('users')
.map(users => {
let exists = false;
users.forEach(user => {
if (user.name.toLowerCase() === name.toLowerCase()) {
console.log('Name already exists!');
exists = true;
}
});
return exists;
})
.first()
.toPromise();
