需要在$ stateProvider中执行resolve属性之前解析$ http请求

时间:2015-03-21 10:11:56

标签: angularjs angular-ui-router angular-promise

我正在构建一个将在多个域上运行的角度应用程序。由于每个域上有不同的配置,因此我需要通过调用服务器来获取所有变量。该调用将返回包含不同rest url的JSON对象。 我的问题是我需要在“解决问题”之前做这个电话。步入$ stateProvider,因为我已经有一个依赖于服务器配置对象的任务。

2 个答案:

答案 0 :(得分:3)

这里应该做的是一个非常棒的功能 $urlRouterProvider.deferIntercept();

$urlRouterProvider

  

deferIntercept(defer)

     

禁用(或启用)延迟位置更改拦截。

     

如果您希望自定义同步URL 的行为(例如,如果您希望延迟转换但保留当前URL),请在配置时调用此方法。然后,在运行时,在配置自己的$urlRouter.listen()事件处理程序后调用 $locationChangeSuccess

API文档中的代码段:

var app = angular.module('app', ['ui.router.router']);

app.config(function($urlRouterProvider) {

  // Prevent $urlRouter from automatically intercepting URL changes;
  // this allows you to configure custom behavior in between
  // location changes and route synchronization:
  $urlRouterProvider.deferIntercept();

}).run(function($rootScope, $urlRouter, UserService) {

  $rootScope.$on('$locationChangeSuccess', function(e) {
    // UserService is an example service for managing user state
    if (UserService.isLoggedIn()) return;

    // Prevent $urlRouter's default handler from firing
    e.preventDefault();

    UserService.handleLogin().then(function() {
      // Once the user has logged in, sync the current URL
      // to the router:
      $urlRouter.sync();
    });
  });

  // Configures $urlRouter's listener *after* your custom listener
  $urlRouter.listen();
});

而且,与此问题相关:

working example - plunker

为了清楚说明,适合这个用例,让我们观察plunker的代码。

因此,首先我们可以看到 .config() 阶段。它确实可以访问提供商,但不能访问其服务(例如$http)。还没有,服务本身将在以后提供......

app.config(function ($locationProvider, $urlRouterProvider, $stateProvider) 
{
    // this will put UI-Router into hibernation
    // waiting for explicit resurrection later
    // it will give us time to do anything we want... even in .run() phase
    $urlRouterProvider.deferIntercept();
    $urlRouterProvider.otherwise('/other');

    $locationProvider.html5Mode({enabled: false});
    $stateProviderRef = $stateProvider;
});

我们所做的是设置对提供者(可配置对象)的引用,稍后将使用:$stateProviderRef

最重要的是我们停止了UI-Router,并迫使他用 $urlRouterProvider.deferIntercept(); 等我们(请参阅doc并在上面引用)

.run() 阶段的摘录:

app.run(['$q', '$rootScope','$http', '$urlRouter',
  function ($q, $rootScope, $http, $urlRouter) 
  {

   // RUN phase can use services (conigured in config phase)
   // e.g. $http to load some data
    $http
      .get("myJson.json")
      .success(function(data)
      {

        // here we can use the loaded stuff to enhance our states
        angular.forEach(data, function (value, key) 
        { 
          var state = { ... }
          ...

          $stateProviderRef.state(value.name, state);
        });
        // Configures $urlRouter's listener *after* your custom listener

        // here comes resurrection of the UI-Router
        // these two important calls, will return the execution to the 
        // routing provider
        // and let the application to use just loaded stuff
        $urlRouter.sync();
        $urlRouter.listen();
      });
}]);

最重要的是,此.run()仅执行 ONCE 。只有一次。我们要求。

我们还可以使用另一种技术:解析一个超级根状态的内部,这是所有状态层次结构根的父级。检查所有详细信息:

Nested states or views for layout with leftbar in ui-router?

答案 1 :(得分:0)

还有另一种解决方法:

  

如何在$http内执行 resolve 属性之前解决$stateProvider请求?

如果我们只需要在 $http 中获得一些resolve结果,我们就可以这样做:

resolve: {
    myResolve1:
        function($http, $stateParams) {
            return $http.get("/api/foos/"+stateParams.fooID);
        }
    }

这是[$stateProvider][1]部分resolve的文档摘录。我们可以看到,我们返回$ http服务的承诺:return $http.get()

所以,要扩展到asnwer:

  

但是如何让ui-router等到承诺得到解决?

我们可以使用return $http.get()然后使用.then()。在其中,我们可以访问返回的结果 - 我们可以调整:

myResolve1:
    function($http, $stateParams) {
        // we still return the promise of the $http.get))
        return $http
          .get("/api/foos/"+stateParams.fooID)
          .then(function(response) {

            // but now, the content of resolved property
            //  will be the first item of the loaded array
            return response.data[0];
          };
     }
}

还有一种解决方案 - 如果我们需要在每个州之前实现这一点。我们只是介绍一些“根”状态作为超级父母。它将包含这样的解决方案,并且所有子状态将等到这个解决后,但只解决了一次。点击此处:angular ui-router resolve for parent state