当页面刷新或深度链接时,angular-ui-router 没有履行状态解析承诺 [英] angular-ui-router isn't fulfilling state resolve promises when page refreshes or deep linked

查看:30
本文介绍了当页面刷新或深度链接时,angular-ui-router 没有履行状态解析承诺的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用 AngularJS 1.2.16、ui-router 和 Restangular(用于 API 服务),我有一个抽象状态和一个使用多个视图的子状态.子视图接受一个 URL 参数(通过 $stateParams)和一个解析以根据通过 URL 传递的给定 ID 从 API 获取记录.

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.

当您在整个站点中导航时,一切都可以完美运行,但是如果您在给定的页面上并刷新它(Command/Ctrl+r 或单击刷新按钮)或通过点击带有 ID 的深层链接直接加载页面(这是更关键的问题)API 服务被请求击中,但承诺从未完成解析,因此数据无法用于状态、控制器、模板等.

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.

根据 ui-router 的文档,在所有 promise 都得到解决之前,不应实例化控制器.我在 Google 和 SO 中进行了高低搜索,阅读了 AngularJS、Restangular 和 ui-router 文档以及大量博客,并尝试了我所知道的每一次迭代来解决这个问题,但找不到任何指向解决方案的内容.

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.

这是有问题的代码:

company.js(控制器代码)

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(使用 Restangular 的 API 服务代码)

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;
      });
    }
  };
}]);

其他一些可以补充的点:* html5mode 为真,带有 hashPrefix* 应用程序由 Apache 提供服务,并设置了重写规则* base href 已设置* 这是整个应用程序特有的问题,数据在一个状态下被解析;我只是选择这个作为例子

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...}

推荐答案

首先只是一个注释.如果你有路由问题(比如 ui-router 的那些),你可以使用像 pastebin 这样的东西来提供一个可以在本地运行的完整演示文件,而不是使用 fiddle,以便可以测试路由问题.

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

有趣的是,您的模拟演示似乎在路由方面工作得非常好.这让我认为问题出在您的生产服务中.ui-router 曾经让我烦恼的一件事是解决 resolve 错误的困难,因为似乎几乎没有错误报告.

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);
});

这篇关于当页面刷新或深度链接时,angular-ui-router 没有履行状态解析承诺的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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