简体   繁体   English

AngularJS应用程序初始化之前的$ http请求?

[英]$http request before AngularJS app initialises?

In order to determine if a user's session is authenticated, I need to make a $http request to the server before the first route is loaded. 为了确定用户的会话是否经过身份验证,我需要在加载第一个路由之前向服务器发出$ http请求。 Before each route is loaded, an authentication service checks the status of the user and the access level required by the route, and if the user isn't authenticated for that route, it redirects to a login page. 在加载每个路由之前,身份验证服务会检查用户的状态以及路由所需的访问级别,如果用户未针对该路由进行身份验证,则会重定向到登录页面。 When the app is first loaded however, it has no knowledge of the user, so even if they have an authenticated session it will always redirect to the login page. 然而,当第一次加载应用程序时,它不知道用户,因此即使他们有经过身份验证的会话,它也将始终重定向到登录页面。 So to fix this I'm trying to make a request to the server for the users status as a part of the app initialisation. 所以为了解决这个问题,我试图向服务器请求用户状态作为应用程序初始化的一部分。 The issue is that obviously $http calls are asynchronous, so how would I stop the app running until the request has finished? 问题是显然$ http调用是异步的,那么在请求完成之前我如何阻止应用程序运行?

I'm very new to Angular and front-end development in general, so my issue maybe a misunderstanding of javascript rather than of Angular. 我对Angular和前端开发很新,所以我的问题可能是对javascript而不是Angular的误解。

You could accomplish that by using resolve in your routingProvider. 您可以通过在routingProvider中使用resolve来实现此目的。

This allows you to wait for some promises to be resolved before the controller will be initiated. 这允许您在启动控制器之前等待一些承诺得到解决。

Quote from the docs: 从文档引用:

resolve - {Object.=} - An optional map of dependencies which should be injected into the controller. resolve - {Object。=} - 应该注入控制器的可选依赖关系映射。 If any of these dependencies are promises, the router will wait for them all to be resolved or one to be rejected before the controller is instantiated. 如果这些依赖项中的任何一个是promise,路由器将等待它们全部被解析或者在实例化控制器之前被拒绝。 If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired. 如果成功解决了所有promise,则会注入已解析的promise的值并触发$ routeChangeSuccess事件。

Simple example 简单的例子

    app.config(['$routeProvider', function($routeProvider) {
    $routeProvider.
        when('/', {templateUrl: 'home.html', controller: 'MyCtrl',resolve: {
            myVar: function($q,$http){
                var deffered = $q.defer();

                    // make your http request here and resolve its promise

                     $http.get('http://example.com/foobar')
                         .then(function(result){
                             deffered.resolve(result);
                          })

                return deffered.promise;
            }
        }}).
        otherwise({redirectTo: '/'});
}]);

myVar will then be injected to your controller, containing the promise data. 然后将myVar注入到包含promise数据的控制器中。

Avoiding additional DI parameter 避免额外的DI参数

You could also avoid the additional DI parameter by returning a service you were going to inject anyways: 您还可以通过返回您要注入的服务来避免额外的DI参数:

app.config(['$routeProvider', function($routeProvider) {
        $routeProvider.
            when('/', {templateUrl: 'home.html', controller: 'MyCtrl',resolve: {
                myService: function($q,$http,myService){
                  var deffered = $q.defer();

                      /*  make your http request here
                      *   then, resolve the deffered's promise with your service.
                      */

                  deffered.resolve(myService),

                  return deffered.promise;
                }
            }}).
            otherwise({redirectTo: '/'});
    }]);

Obviously, you will have to store the result from your request anywhere in a shared service when doing things like that. 显然,在执行此类操作时,您必须将请求的结果存储在共享服务中的任何位置。


Have a look at Angular Docs / routeProvider 看看Angular Docs / routeProvider

I have learned most of that stuff from that guy at egghead.io 我从egghead.io的那个人那里学到了很多东西

Encapsulate all your resources with a sessionCreator and return a promise. 使用sessionCreator封装所有资源并返回一个promise。 After resolve then to your controller so you can keep it free of specific promise code. 然后resolve之后到您的控制器,这样您就可以保持它没有特定的promise代码。

app.factory('sessionCreator', ['$http', '$q', 'urlApi',

  function ($http, $q, urlApi) {
    var deferred = $q.defer();

    $http.get(urlApi + '/startPoint').success(function(data) {
      // Do what you have to do for initialization.
      deferred.resolve();
    });

    return deferred.promise;
  }

]);

app.factory('Product', ['$resource', 'urlApi', 'sessionCreator',

  function($resource, urlApi, sessionCreator) {
    // encapsulate all yours services with `sessionCreator`
    return sessionCreator.then(function() {
      return $resource(urlApi + '/products', {}, {
        query: {method:'GET', params:{}, isArray: true}
      });
    });
  }

]);

app.config(['$routeProvider', function ($routeProvider) {

  var access = routingConfig.accessLevels;

  $routeProvider
    .when('/product', {
      templateUrl: 'views/products.html', controller: 'ProductCtrl',
      // resolve then in router configuration so you don't have to call `then()` inside your controllers
      resolve: { Product: ['Product', function(Product) { return Product; }] }
    })
    .otherwise({ redirectTo: '/' });
}]);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM