2017-01-07 4 views
1

私は、observableを使用して最初のイベントをリッスンするメソッドを持ち、タイムアウトは15秒です。このメソッドは、パラメータがnullまたは空の場合はエラーをスローするネストされたobservableを呼び出します。 Observable.throw()を使用しますが、エラーはタイムアウト/ 15秒後にのみ伝播します。ネストされたobservableは、タイムアウト後にのみエラーを伝播します

this.signUp(this.user) 
      .first() 
      .timeout(15000) 
      .subscribe((authResponse) => { 
       console.log("next fired"); 
       dialogs.alert("Next: " + authResponse); 
      }, (error) => { 
       //fired only after 15s when mobile is empty 
       console.log("error fired"); 
       console.log(JSON.stringify(error)); 
      },() => { 
       console.log("completed fired"); 
      }); 

サインアップ()

public signUp(user: User): Observable<AuthResponse> { 
     let observable = new Subject<AuthResponse>(); 
     this.isUserExisting(user.mobile) 
      .first() 
      .subscribe((isUserExisting) => { 
       if (isUserExisting) { 
        console.log("User already exists"); 
        observable.next(AuthResponse.USER_EXISTING); 
       } else { 
        console.log("User does not exist"); 
        this.saveUser(user).first().subscribe(() => { 
         observable.next(AuthResponse.SUCCESS); 
        }) 
       } 
      }, (error) => { 
       return Observable.throw(error); 
      }) 
     return observable; 
    } 

    public isUserExisting(mobile: string): Observable<boolean> { 
     let observable = new Subject<boolean>(); 
     if (!mobile) { 
      console.log("empty mobile"); 
      return Observable.throw(new Error("Mobile number cannot be empty")); 
     } 
     firebase.query(() => { }, "/users", 
      { 
       singleEvent: true, 
       orderBy: { 
        type: firebase.QueryOrderByType.CHILD, 
        value: "mobile" 
       }, 
       range: { 
        type: firebase.QueryRangeType.EQUAL_TO, 
        value: mobile 
       } 
      } 
     ).then((result) => { 
      console.log("Checking for user success: "); 
      console.log(JSON.stringify(result)); 
      observable.next(result.value != null); 
     }); 
     return observable; 
    } 

更新: saveUser()

public saveUser(user: User) { 
     return Observable.defer(() => firebase.push('/users', user) 
      .then((result) => { 
       console.log("Created user record with key: " + result.key); 
       console.log("Dumping result:"); 
       console.log(JSON.stringify(result)); 
      }) 
      .catch((error) => { 
       console.log("Error while saving user: " + error); 
      }) 
     ) 
    } 

答えて

1

あなたがされている観測可能な値を放出先となる独自の件名を作成するために、悪い習慣です内部のサブスクライブされたオブザーバブルから放出される。これは、あなたが内部サブスクリプションから退会する方法がないので、メモリリークにつながります。あなたのコードがそれから退会することができますし、エラーがあなたの側上の任意の作業をせずに伝播され、あなたのsignUp機能では、サブスクリプションなし

public signUp(user: User): Observable<AuthResponse> { 
    return this.isUserExisting(user.mobile) 
    .flatMap(isExistingUser => { 
     if (isExistingUser) { 
     console.log('user already exists: ' + isUserExisting); 
     return Rx.Obserable.of(AuthResponse.USER_EXISTING); 
     } 
     return saveUser(user).map(result => AuthResponse.SUCCESS) 
    }) 
    .catch(err => { 
     console.log(`error during signup of user: ${user.mobile})`); 
     return Rx.Observable.of(AuthResponse.FAILED_TO_SIGNUP); 
    }) 
    .first(); 
} 

これは、あなたの携帯電話番号のチェックの代わりにあなたのタイムアウトがヒットした理由です。エラーを伝播するのを忘れました。代わりに、subscribeOnErrorコールバック内のRx.Observable.throwを返信しようとしました。onError(error):void

あなたのRx機能を怠惰な状態に保つことをお勧めします。誰かがそれを購読しているときにのみコードを実行してください。これは、エラーの追跡を困難にするのに役立ちます。 firebase.query()を使用して(約束を返します)、.defer()を使用して、誰かがあなたのisUserExisting関数を購読するまで約束を実行するのを待つことができます。 .defer()、それが右起動する前に、サブスクリプションのために待機していましたので、.fromPromise()よりも、それを使用するのが最善であるに関する

public isUserExisting(mobile: string): Observable<boolean> { 
    if (!mobile) { 
     console.log("empty mobile"); 
     return Observable.throw(new Error("Mobile number cannot be empty")); 
    } 

    return Rx.Observable.defer(() => firebase.query(() => { }, "/users", 
     { 
      singleEvent: true, 
      orderBy: { 
       type: firebase.QueryOrderByType.CHILD, 
       value: "mobile" 
      }, 
      range: { 
       type: firebase.QueryRangeType.EQUAL_TO, 
       value: mobile 
      } 
     } 
)) 
    .do(firebaseResult => console.log('Checking for user success: ' + JSON.stringify(firebaseResult))) 
    .filter(firebaseResult => firebaseResult.value != null); 
} 

public saveUser(user: User) { 
    return Observable.defer(() => firebase.push('/users', user)) 
    .do(result => console.log(`created user with key ${result.key}`)) 
} 
+1

? – danieljohngomez

+0

また、ネストされたobservable saveUser()を呼び出すにはどうすればよいですか? – danieljohngomez

+0

こんにちはDaniel、はい私の経験では、ほとんどの場合、fromPromise()の代わりに 'defer()'を使いたいと思っています。元の答えを更新して、 'saveUser()'メソッドを組み込んでいます。 'signUp(user).subscribe(res => console.log(res))'は、実行するために必要なものです –

関連する問題