ほとんどのルートにアクセスする前に認証が必要な Play + AngularJS を使用して構築している単純なアプリがあります。ログイン フローには、セッション ID をブラウザーのローカル ストレージに保存し、ユーザーがアプリに戻るたびに、サーバー側の有効な承認済みデータベース セッション エントリにマップされる "remember me" 機能が含まれています。
私が抱えている問題は、モジュールのrun() 関数でセッション チェック (Cookie を抽出し、サーバーと比較する) を行うことです。
.run(function ($rootScope, $http, $cookieStore, $location) {
// <snip>
// check if there is already a session?
var sessionId = window.localStorage["session.id"];
if (sessionId == null) {
sessionId = $cookieStore.get("session.id");
}
if (sessionId != null) {
$http.get("/sessions/" + sessionId)
.success(function (data) {
$http.defaults.headers.common['X-Session-ID'] = data.id;
$cookieStore.put("session.id", data.id);
$rootScope.user = data.user;
})
.error(function () {
// remove the cookie, since it's dead
$cookieStore.remove("session.id");
window.localStorage.removeItem("session.id");
$location.path("/login");
});
} else {
if ($location.path() != "/login" && $location.path() != "/signup") {
$location.path("/login");
}
}
});
問題は、この関数が AJAX 呼び出しを実行し、完了するまでセッションが有効かどうかわからないことです。ただし、($routeProvider によって選択されたルートを介して) ロードするコントローラーは、他の AJAX 呼び出しが終了する前に開始されることが多い別の AJAX 呼び出しを起動する可能性があり、その結果、競合状態になり、最初の要求で 401 応答コードが返されます。
だから私の質問は、アプリの他の部分が実行される前に、実行を強制的に (関連する $http 呼び出しで) 完了するにはどうすればよいですか? ここで $q/promise を使用してみましたが、違いはないようです (おそらく実行関数は約束を尊重しません)。私は$routeProviderresolve
の機能を使用するようにアドバイスしてきましたが、何をすべきか正確にはわかりません。とにかく、すべてのルートにそれを入れなければならないことにあまり興奮していません.
これはかなり一般的なユースケースであり、毎日解決されていると思います。うまくいけば、誰かが私のコードで何らかの方向性を教えてくれたり、「remember me」と AngularJS のアプローチを共有したりできます。