web-dev-qa-db-ja.com

Angular 2 FirebaseObservableが約束しても何も返されません

私は現在、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ループを停止する方法はありますか?

これに対する答えがまったく見つからなかったので、どんな助けでも大歓迎です。

14
Leonidas

問題は、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();
28
cartant