2013-11-27 26 views
4

有點信息。我正在研究單個頁面的應用程序,但是試圖將其製作爲HTML文件,而不是包含其中所有引導程序信息的實際動態頁面。我也希望在應用啓動時(或者在之前)檢查當前會話是否「登錄」,如果沒有,則將該散列指向「登錄」。在Angular中,如何在啓動之前從服務器獲取引導數據?

我新的角度,和我有困難的時候搞清楚如何編寫出這個流程。因此,從本質..

  1. HTML網頁加載與「遞延」引導
  2. 命中URL獲得登錄狀態
  3. 如果狀態爲「未登錄」,直接到#/登錄
  4. 開始應用

在哪裏#2,#3將住任何指針?在我的'簡單的世界'中,我只是使用jquery來獲取這些數據,然後致電angular.resumeBootstrap([appname])。但是,由於我試圖實際學習Angular,而不是僅僅圍繞我不明白的部分進行攻擊,所以我想知道在這個地方會用到什麼。我在看供應商,但我不確定那是我需要的。

謝謝!

編輯

基於@ Mik378的回答,我已經更新了我的代碼以下爲測試。它的工作原理到一個點,但隨着「得到」是異步,它允許應用程序繼續加載不管它是什麼,然後拍攝過的狀態結果之前..

var app = angular.module('ping', [ 
    'ngRoute', 
    'ping.controllers' 
]).provider('security', function() { 
    this.$get = ['$http', function($http) { 
      var service = { 
       getLoginStatus: function() { 
        if (service.isAuthenticated()) 
         return $q.when(service.currentUser); 
        else 
         return $http.get('/login/status').then(function (response) { 
          console.log(response); 
          service.loggedIn = response.data.loggedIn; 
          console.log(service); 
          return service.currentUser; 
         }); 
       }, 
       isAuthenticated: function() { 
        return !!service.loggedIn; 
       } 
      }; 
      return service; 
     }]; 
}).run(['security', function(security) { 
     return security.getLoginStatus().then(function() { 
      if(!security.isAuthenticated()) { 
       console.log("BADNESS"); 
      } else { 
       console.log("GOODNESS"); 
      } 
     }); 
}]); 

我的希望是,這可以在某種程度上完成在第一個控制器啓動之前,這樣它就不會加載(或試圖加載)甚至還沒有被清除以進行訪問的事情。

編輯#2

我開始尋找到路由器中的「解析」屬性,@ Mik378覈實我所期待的。我是(目前)工作如何我想如下(appologies對超長代碼塊)

angular.module('ping.controllers', []) 
     .controller('Dashboard', ['$scope', function($scope) { 
      console.log('dashboard') 
     }]) 
     .controller('Login', ['$scope', function($scope) { 
      console.log('login') 
     }]); 

var app = angular.module('ping', [ 
    'ngRoute', 
    'ping.controllers' 
]).run(['$rootScope', '$location', function($root, $location) { 
    $root.$on("$routeChangeError", function (event, current, previous, rejection) { 
     switch(rejection) { 
      case "not logged in": 
       $location.path("/login"); //<-- NOTE #1 
       break; 
     } 
    }); 
}]); 

app.provider('loginSecurity', function() { 
    this.$get = ['$http', '$q', function($http, $q) { 
      var service = { 
       defer: $q.defer, //<-- NOTE #2 
       requireAuth: function() { //<-- NOTE #3 
        var deferred = service.defer(); 
        service.getLoginStatus().then(function() { 
         if (!service.isAuthenticated()) { 
          deferred.reject("not logged in") 
         } else { 
          deferred.resolve("Auth OK") 
         } 
        }); 
        return deferred.promise; 
       }, 
       getLoginStatus: function() { 
        if (service.isAuthenticated()) { 
         return $q.when(service.currentUser); 
        } else { 
         return $http.get('/login/status').then(function(response) { 
          console.log(response); 
          service.loggedIn = response.data.loggedIn; 
          console.log(service); 
          return service.currentUser; 
         }); 
        } 
       }, 
       isAuthenticated: function() { 
        return !!service.loggedIn; 
       } 
      }; 
      return service; 
     } 
    ]; 
}); 

app.config(['$routeProvider', function($routeProvider) { 
     console.log('Routing loading'); 
     $routeProvider.when('/', { 
      templateUrl: 'static/scripts/dashboard/template.html', 
      controller: 'Dashboard', 
      resolve: {'loginSecurity': function (loginSecurity) { 
       return loginSecurity.requireAuth(); //<- NOTE #4 
      }} 
     }); 
     $routeProvider.when('/login', { 
      templateUrl: 'static/scripts/login/template.html', 
      controller: 'Login' 
     }); 
     $routeProvider.otherwise({redirectTo: '/404'}); 
}]); 

注意最終代碼:

  1. 本節掛接到路由故障。在「不登錄」的情況下,我想要捕捉失敗並將其推送到登錄頁面。
  2. 我無法訪問requireAuth函數內的$ Q,所以我抓住一個參考吧。也許有更好的方式來做到這一點?
  3. 此功能包裝了另外兩個 - 它使用從getLoginStatus返回的承諾,但如果從getLoginStatus最終結果與用戶沒有登錄捲起返回了自己的承諾,將被拒絕排序廿四的。關於這樣做的方式。
  4. 這將返回#3的承諾,這是用來由$ routeProvider ..所以如果失敗,路由失敗,你最終在#1接住。

呼。我認爲這足夠一天。時間喝啤酒。

+0

是否有一個原因,你不想在另一個角度路線執行此檢查,然後執行重定向? – eddiec

+0

不是,不 - 我只是習慣在啓動時檢查。 – Stephen

回答

2

無需使用遞延引導你的情況:

angular.module('app').run(['security', '$location', function(security) { 
    // Get the current user when the application starts 
    // (in case they are still logged in from a previous session) 
    security.requestCurrentUser().then(function(){ 
     if(!security.isAuthenticated()) 
     $location.path('yourPathToLoginPage') 
    }; //service returning the current user, if already logged in 
}]); 

這種方法requestCurrentUser是以下幾點:

requestCurrentUser: function() { 
        if (service.isAuthenticated()) 
         return $q.when(service.currentUser); 
        else 
         return $http.get('/api/current-user').then(function (response) { 
          service.currentUser = response.data.user; 
          return service.currentUser; 
         }); 
       } 

和內再次security服務:

isAuthenticated: function() { 
        return !!service.currentUser; 
       } 

注意模塊的run方法=>儘快應用程序運行,這個服務被調用。

- 更新 -

爲了防止requestCurrentUser提供的承諾得到解決之前,一個更好的解決方案進行初始化任何控制器,如在下面的評論引起的,是使用resolve路線屬性。

+0

啊,這實際上似乎是有道理的。讓我玩一下,我會告訴你的! – Stephen

+0

@Stephen好吧,讓我知道;) – Mik378

+1

好吧 - 有一件事可能是一個疏忽(或者我沒有做正確的事情)。 '$ http.get'當然是async ..這很好,因爲它返回一個承諾對象。但是,調用requestCurrentUser只是返回一個promise對象。在下一行命中時(在'if(!security.isAuthenticated())'),不會準備好這些數據。現在,在我的代碼中,我已經使用承諾對象來執行'.then'內部的承諾對象,但它並不能真正阻止任何其他控制器的加載或在應用程序真正啓動之前完成。 – Stephen

相關問題