棱角分明的UI路由器不履行国家承诺的决心时,页面刷新或深层链接 [英] angular-ui-router isn't fulfilling state resolve promises when page refreshes or deep linked

查看:161
本文介绍了棱角分明的UI路由器不履行国家承诺的决心时,页面刷新或深层链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用AngularJS 1.2.16,UI的路由器和Restangular(对于API服务),我有一个使用多个视图子状态的抽象状态。子视图接受一个URL参数(通过$ stateParams)和决心,从基础上通过URL传递给定ID的API获取该记录。

所有完美的作品在您浏览网站,但是,如果你是在给定的页面上并刷新它(命令/ Ctrl + R键或单击刷新按钮)或直接击中该ID的深层链接加载页面(这是更关键的问题)的API服务是由请求击中,但承诺永远不会完成解析,因此数据不能提供给状态,控制器,模板等。

据UI的路由器的文档,控制器不应该被实例化,直到所有的承诺都解决了。我已经搜查高和低的谷歌和SO,阅读AngularJS,Restangular和UI路由器文档和博客众多,并试图每次迭代我知道这个号码并不能找到任何指向一个解决方案

下面是有问题的code:

company.js (控制器code)

  angular.module('my.company',['ui.router','CompanySvc'])的.config(['$ stateProvider',功能配置($ stateProvider){
  $ stateProvider
    .STATE('公司',{
      摘要:真实,
      网址:'/公司,
      数据:{
        PAGETITLE:本公司
      },
      观点:{
        '主':{
          templateUrl:公司/ companyMain.tpl.html
        }
      }
    })
    .STATE('company.landing',{
      网址:'/ {ID}
      观点:{
        摘要:{
          控制器:'CompanyCtrl',
          templateUrl:公司/ companyDetails.tpl.html
        },
        位置:{
          控制器:'CompanyCtrl',
          templateUrl:公司/ companyLocations.tpl.html
        }
      },
      解析:{
        companySvc:CompanySvc',
        //检索公司的报告显示,如果id为present
        公司:['$日志,$ stateParams','companySvc',函数($日志$ stateParams,companySvc){
          $ log.info(在company.landing:解决和$ stateParams是:',$ stateParams);          VAR ID = $ stateParams.id;          $ log.info(在company.landing:解决id是:'ID);          返回companySvc.getCompany(ID)$承诺。          //注意SO:这是在获得解决的承诺又刺,
          //左注释掉,以供参考
          / *返回companySvc.getCompany(ID)。然后(功能(响应){
            返回响应;
          }); * /
        }]
      }
    });
  }
]).controller('CompanyCtrl',['$日志,$范围,$状态','公司',
  功能CompanyCtrl($日志,$范围,$状态,公司){
    $ log.info(在CompanyCtrl&放大器; $状态是:,$状态);
    $ log.info(在CompanyCtrl和公司的数据是:'公司);
    $ scope.reportData =公司?公司:{};
    $ log.info(在CompanyCtrl和$ scope.reportData是:',$ scope.reportData);
  }
]);

companyService.js (API服务$ C $使用Restangular C)

  angular.module('my.companyService',['restangular']);.factory('CompanySvc',['$日志','Restangular',函数($日志,Restangular){
  VAR restAngular = Restangular.withConfig(功能(配置器){
    Configurer.setBaseUrl('/ INT');
  });  // Object对个别公司的工作
  变种_companySvc = restAngular.all('公司');  //暴露我们的CRUD方法
  返回{
    //获取一个记录/ INT /公司/ {ID} /报告
    getCompany:功能(ID){
      $ log.info(在CompanySvc.getCompany和ID是:',身份证);      返回restAngular.one('公司',ID).customGET(报告),然后(函数成功(响应){
        $ log.info('检索公司:',响应);        返回响应;
      },功能错误(原因){
        $ log.error('错误:检索公司:,原因);        返回false;
      });
    }
  };
}]);

这可以增加一些其他的要点:
* html5mode是一个哈希preFIX真
*应用程序正在被Apache服务与重写规则设置
*基本href设置
*这是特有的,其中数据是在一个国家得到解决整个应用程序的问题;我只是选择这个作为例子

最后,这里是从控制台一些输出:

 在company.landing:解决和$ stateParams是:对象{ID =d2c936fb78724880656008a5545b01ea445d4dc4}
在company.landing:决心和id是:d2c936fb78724880656008a5545b01ea445d4dc4
在CompanySvc.getCompany&安培; ID为:d2c936fb78724880656008a5545b01ea445d4dc4 \\
在CompanyCtrl&安培; $状态是:对象{PARAMS = {...},电流= {...},$电流= {...},更...}
在CompanyCtrl和公司的数据是:未定义
在CompanyCtrl和$ scope.reportData是:对象{}
在CompanyCtrl&安培; $状态是:对象{PARAMS = {...},电流= {...},$电流= {...},更...}
在CompanyCtrl和公司的数据是:未定义
在CompanyCtrl和$ scope.reportData是:对象{}
在CompanyCtrl&安培; $状态是:对象{PARAMS = {...},电流= {...},$电流= {...},更...}
检索公司:对象{$承诺= {...},$ =解决了假,路线=公司,更...}


解决方案

首先只是一个音符。如果你有路由问题(像那些与UI的路由器),而是采用了小提琴,你可以使用类似引擎收录,以提供可以在本地运行一个完整的演示文件,这样的路线问题,可以进行测试。

我创建了那些来自你的小提琴之一:这里

有趣的是,你的模拟演示似乎完全正常工作与问候路由。这让我觉得,问题在于你生产的服务的地方。即用于骚扰我, UI路由器的一件事是在解决困难解析的错误,因为似乎有几乎没有错误报告。

如果您添加到您的应用程序运行的功能(如我在上面的链接都做),你应该得到更好地解决错误输出:

  //处理任何路由相关的错误(特别是用于检查隐藏的决心错误)
$ rootScope。在$('$ stateChangeError',函数(事件,toState,toParams,fromState,fromParams,错误){
    的console.log(错误);
});

Using AngularJS 1.2.16, ui-router, and Restangular (for API services), I have an abstract state with a child state that uses multiple views. The child view accepts a URL parameter (via $stateParams) and a resolve to fetch the record from an API based on the given ID passed via the URL.

All works perfectly as you navigate throughout the site, however if you are on the given page and refresh it (Command/Ctrl+r or clicking the refresh button) or load the page directly by hitting the deep link with the ID (this is the more crucial problem) the API service is hit by the request but the promise never finishes resolving, thus the data isn't made available to the state, controller, templates, etc.

According to ui-router's documentation, controllers shouldn't be instantiated until all promises are resolved. I've searched high and low in Google and SO, read the AngularJS, Restangular, and ui-router documentation, and a multitude of blogs and tried every iteration I know to figure this out and can't find anything that points to a solution.

Here's the code in question:

company.js (controller code)

angular.module('my.company', ['ui.router', 'CompanySvc'])

.config(['$stateProvider', function config ($stateProvider) {
  $stateProvider
    .state('company', {
      abstract: true,
      url: '/company',
      data: {
        pageTitle: 'Company'
      },
      views: {
        'main': {
          templateUrl: 'company/companyMain.tpl.html'
        }
      }
    })
    .state('company.landing', {
      url: '/{id}',
      views: {
        'summary': {
          controller: 'CompanyCtrl',
          templateUrl: 'company/companyDetails.tpl.html'
        },
        'locations': {
          controller: 'CompanyCtrl',
          templateUrl: 'company/companyLocations.tpl.html'
        }
      },
      resolve: {
        companySvc: 'CompanySvc',
        // Retrieve a company's report, if the id is present
        company: ['$log', '$stateParams', 'companySvc', function ($log, $stateParams, companySvc) {
          $log.info('In company.landing:resolve and $stateParams is: ', $stateParams);

          var id = $stateParams.id;

          $log.info('In company.landing:resolve and id is: ', id);

          return companySvc.getCompany(id).$promise;

          // NOTE SO: this was another stab at getting the promise resolved,
          // left commented out for reference
          /*return companySvc.getCompany(id).then(function (response) {
            return response;
          });*/
        }]
      }
    });
  }
])

.controller('CompanyCtrl', ['$log', '$scope', '$state', 'company',
  function CompanyCtrl ($log, $scope, $state, company) {
    $log.info('In CompanyCtrl & $state is: ', $state);
    $log.info('In CompanyCtrl and company data is: ', company);
    $scope.reportData = company ? company : {};
    $log.info('In CompanyCtrl and $scope.reportData is: ', $scope.reportData);
  }
]);

companyService.js (API service code using Restangular)

angular.module('my.companyService', ['restangular']);

.factory('CompanySvc', ['$log', 'Restangular', function ($log, Restangular) {
  var restAngular = Restangular.withConfig(function (Configurer) {
    Configurer.setBaseUrl('/int');
  });

  // Object for working with individual Companies
  var _companySvc = restAngular.all('companies');

  // Expose our CRUD methods
  return {
    // GET a single record /int/companies/{id}/report
    getCompany: function (id) {
      $log.info('In CompanySvc.getCompany & id is: ', id);

      return restAngular.one('companies', id).customGET('report').then(function success (response) {
        $log.info('Retrieved company: ', response);

        return response;
      }, function error (reason) {
        $log.error('ERROR: retrieving company: ', reason);

        return false;
      });
    }
  };
}]);

Some other points that may be added: * html5mode is true with a hashPrefix * app is being served by Apache with rewrite rules set * base href is set * this is a problem endemic to the entire application where data is being resolved in a state; I just chose this as the example

Finally, here's some output from the console:

In company.landing:resolve and $stateParams is: Object { id="d2c936fb78724880656008a5545b01ea445d4dc4"}
In company.landing:resolve and id is: d2c936fb78724880656008a5545b01ea445d4dc4
In CompanySvc.getCompany & id is: d2c936fb78724880656008a5545b01ea445d4dc4\
In CompanyCtrl & $state is: Object { params={...}, current={...}, $current={...}, more...}
In CompanyCtrl and company data is: undefined
In CompanyCtrl and $scope.reportData is: Object {}
In CompanyCtrl & $state is: Object { params={...}, current={...}, $current={...}, more...}
In CompanyCtrl and company data is: undefined
In CompanyCtrl and $scope.reportData is: Object {}
In CompanyCtrl & $state is: Object { params={...}, current={...}, $current={...}, more...}
Retrieved company: Object { $promise={...}, $resolved=false, route="companies", more...}

解决方案

Firstly just a note. If you have routing issues (like those with ui-router), instead of using a fiddle, you can just use something like pastebin to provide a single complete demo file that can be run locally, so that the route issues can be tested.

I have created one of those from your fiddle: here

The interesting thing is, that your mock demo seems to work perfectly fine with regards to routing. This makes me think that the issue lies somewhere in your production service. One thing that used to annoy me with ui-router was the difficulty in solving resolve bugs, as there seemed to be little to no error reporting.

If you add this to your apps run function (as I have done in the link above), you should get better resolve error output:

// handle any route related errors (specifically used to check for hidden resolve errors)
$rootScope.$on('$stateChangeError', function(event, toState, toParams, fromState, fromParams, error){ 
    console.log(error);
});

这篇关于棱角分明的UI路由器不履行国家承诺的决心时,页面刷新或深层链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆