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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/19654195/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 16:21:22  来源:igfitidea点击:

$http request before AngularJS app initialises?

javascriptangularjs

提问by Ben Davis

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. 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 请求。在加载每个路由之前,身份验证服务会检查用户的状态和路由所需的访问级别,如果用户未通过该路由的身份验证,则会重定向到登录页面。然而,当应用程序第一次加载时,它不知道用户,所以即使他们有一个经过身份验证的会话,它也总是会重定向到登录页面。所以为了解决这个问题,我正在尝试向服务器请求用户状态作为应用程序初始化的一部分。问题是显然 $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 的误解。

采纳答案by Wottensprels

You could accomplish that by using resolvein your routingProvider.

您可以通过resolve在您的 routingProvider 中使用来实现这一点。

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. 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. If all the promises are resolved successfully, the values of the resolved promises are injected and $routeChangeSuccess event is fired.

解析 - {Object.=} - 应该注入控制器的可选依赖关系图。如果这些依赖中的任何一个是 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 将被注入到您的控制器中,其中包含承诺数据。

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的那个人那里学到了大部分东西

回答by armoucar

Encapsulate all your resources with a sessionCreatorand return a promise. After resolvethen to your controller so you can keep it free of specific promisecode.

用 a 封装你的所有资源sessionCreator并返回一个 promise。之后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: '/' });
}]);