2017-03-16 10 views
7

私はビルド中のモバイルアプリケーションを持っていますし、今は認証に取り組んでいます。ホームページにアクセスする前に、ユーザーにデータを表示する前に、作成したAPIのさまざまなエンドポイントをヒットする必要があります。角2は複数の非同期メソッドを呼び出します

郵便配達でテストした場合、すべてのエンドポイントが正しいデータを返していますが、私のアプリケーションでは2番目の非同期コールでnullという値が得られます。

私はそれがこれらの呼び出しが行われる順序と関係があると確信していますので、私はちょうど1つの呼び出しが別の呼び出しを開始する前に終了するのを適切に待つ方法についていくつかの助けを探していました。

public login() { 

this.showLoading(); 

this.userService.getUserIdFromUserName(this.registerCredentials.username) // WORKS 
    .subscribe(
    res => { 
     console.log(res); 
     localStorage.setItem("UserId", res.toString()); 
    }, 
    err => { 
     console.log(err); 
    }); 

this.userService.getEmployeeIdFromUserId(localStorage.getItem("UserId")) // THIS RETURNS NULL 
    .subscribe(
    res => { 
     console.log(res); 
     localStorage.setItem("EmployeeId", res.toString()); 
    }, 
    err => { 
     console.log(err); 
    }); 

this.authService.login(this.registerCredentials) 
    .subscribe(

    data => { 
     this.loading.dismissAll(); 
     console.log('User logged in successfully! ', data); 
     this.nav.push(TabsPage); 
     localStorage.setItem("Username", this.registerCredentials.username); 
     localStorage.setItem("isLoggedIn", "true"); 
    }, 

    error => { 
     this.loading.dismissAll(); 
     this.showAlert("Uh oh!", "Something went wrong. Please re-enter your login credentials or check your connection."); 
     console.log(error); 
    }); 
    } 
+0

タイトルは 'Angular2'が、キーワードは言う: あなたがC)並列に実行できる場合は、あなたが.mergeMap()の説明に手を必要とする場合は、この答えを見て、最後に.forkJoin().

を見て「angularjs」と言う。あなたは2つのうちの1つを修正することを検討することができます – ConnorsFan

+0

あなたは[この回答](http://stackoverflow.com/a/35268597/1009922)で必要なものを見つける必要があります。 – ConnorsFan

答えて

14

忘れwork.Don't必要があります。

A) this.userService.getUserIdFromUserName(this.registerCredentials.username) // WORKS 

B) this.userService.getEmployeeIdFromUserId(localStorage.getItem("UserId")) // THIS RETURNS NULL 

C) this.authService.login(this.registerCredentials) 
あなたがRXJSについて理解する必要がどのような

が必要なすべての情報を表して観察可能冷たい(の差です:あなたは3つの、私がAを呼び出しますあなたのコード内のコール)、B)、およびC)を持っていますstart非同期操作)とhot Observable(非同期操作でObservableであり、すでにが開始されました。)です。

A)、B)、C)の3つの呼び出しは、単に.subscribe()と呼ぶ瞬間に開始されるコールドオブザーバブルを作成するだけです。 B)が構築されるまでに、A)はすでに開始されていますが、まだ完了していません。したがって、localStorage.getItem("UserId")の呼び出しは、A)がまだそのサブスクライバのnextコールバックを呼び出していないため、nullを返します。

あなたがしたいことは、B)がA)を待つことです。また、グローバル状態(localStorage)に何かを詰め込むのではなく、A)からB)に結果を流す方がよいでしょう。 .mergeMap()オペレータ入力します。

this.userService.getUserIdFromUserName(this.registerCredentials.username) // WORKS 
    .map(res => res.toString()) 
    .do(userId => localStorage.setItem("UserId", userId)) // cleanly separate side-effects into .do() calls 
    .mergeMap(userId => this.userService.getEmployeeIdFromUserId(userId)) 
    .map(res => res.toString()) 
    .do(employeeId => localStorage.setItem("EmployeeId", employeeId)) 
    .subscribe(
    employeeId => { 
     console.log(employeeId);  
    }, 
    err => { 
     console.log(err); 
    }); 

をrxjsのいいところは、エラーハンドリングは自分の観察可能なチェーンを介してすべての道を動作することです。 SwitchMap vs MergeMap in the #ngrx example

+0

+1:すばらしい答え。本当に分かりやすく、全体的にきれいなコードがここにあります。明らかにこれはあなたとは関係ありませんが、私はRxJSオペレータがより良い名前を持っていればいいと思っています。人々は 'flatMap'(これもまた素晴らしい名前です)と一緒に行ったので、' selectMany'(これは素晴らしい名前でした)から離れたがっていました。両方とも、コレクションとの類推を保存しています。 'mergeMap'はソートの何もしません。順序の点では説明的かもしれませんが、意図的に直感を提供するように名前が付けられていても、それは悲惨に失敗します。彼らはそれを「バインド」するように名前を変更し、それを使って行うこともできます。 –

+0

質問:より良い解決策をswitchmapしないでしょうか? (私は違いを知っていますが、それでも...) –

0

これはあなたの元のコードは、このエラーにつながるバグがありimport 'rxjs/Rx'

this.userService.getUserIdFromUserName(this.registerCredentials.username) 
    .map(res => res.toString()) 
    .do(userId => { 
     console.log(res); 
     localStorage.setItem("UserId", userId); 
    }) 
    .flatMap(userId => { 
     return this.userService.getEmployeeIdFromUserId(userId); 
    }) 
    .do(res => { 
     console.log(res); 
     localStorage.setItem("EmployeeId", res.toString()); 
    }) 
関連する問題