私は現在、AngularFire2でAngular 2プロジェクトに取り組んでおり、FirebaseListObservableをPromiseに変換しようとしています。Observablesの方が便利なので、あまり意味がないことはわかっていますが、この関数は、複数のプロミスがチェーンされている別の関数の一部になります。また、プロミスのチェーン内でObservablesをサブスクライブする方法に慣れていません...この関数はサービスで実行されますが、何も返さないようです。基本的に、私がやりたいのは、特定の名前のオブジェクトがすでに存在するかどうかをFirebaseリストでチェックし、trueまたはfalseのいずれかを返すことです。
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();
}
constructor(private _usersService: UsersService) { }
check(name) {
this._usersService.nameExists(name)
.then(bool => console.log(bool));
}
そのため、一致するものがあると、関数が実行され、コンソールに出力されるときに正しく機能しているように見えます。ただし、コンポーネントのconsole.log()は実行されません。 「当時」の部分には決して到達しないと思います。別の注意点として、一致が見つかったらforEachループを停止する方法はありますか?
これに対する答えがまったく見つからなかったので、どんな助けでも大歓迎です。
問題は、toPromise
演算子が、オブザーバブルを、オブザーバブルの最終値に解決されるプロミスに変換することです。つまり、Promiseが解決する前にオブザーバブルを完了する必要があります。
AngularFire2では、リストとオブジェクトのオブザーバブルは完了しません。データベースが変更されるたびに再発行します。
first
演算子を使用して問題を解決できます。この演算子は、最初に出力された値を取得してから、合成されたオブザーバブルを完成させます。
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();