为什么 angular 在路由器解析完成之前解析模板?

Why does angular parse templates before router resolved is done?

我正在使用 angular 和 ng-route,如果某些给定的解析 returns false,我想处理一个简单的重定向。但是,如果路由的模板包含 ng-bind-html,则会触发 "Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context." 错误,即使没有理由在解析之前加载模板。我找到的唯一解决方案是 return null(false 不起作用)从 resolve...

https://jsfiddle.net/pansay/wLkxkp5e/3/

.when('/abc/:id', {
        template: 'should not get here <span ng-bind-html="ctrl.someData"></span>', // if :id was not found
         controller: ['someData', function (someData) {
               this.someData = someData;
           }],
           controllerAs: 'ctrl',
        resolve: {
            someData: ['$location', function ($location) {
                // actual case: use the :id param to fetch data from some service
                // but redirect if it returns false
                $location.path('/abc');
                return false;
            }]
        }
    })

但这仍然意味着 controller/template 仍然被解析,这似乎不是 desired/documented 的行为并且可能会触发其他问题......是否有充分的理由这样做?

当你从解析中 return false 时,你实际上表明 解析是好的并且 returned 值 false 被传递给范围。所以它在重定向之前进入那个状态,值为 false。因为 someData 是用奇怪的数据解析的,所以你会看到异常等

您需要做的是防止进入该状态,如果您要进行重定向。为此,您需要 return 承诺并拒绝它。

像这样:

someData: ['$location', '$q', function ($location, $q) {
            return fetchFromSomeService.then(
               function(valueFromService) {
                   if(valueFromService === false) {
                     return $q.reject();
                   }
                   return valueFromService; 
               }
          }]

对于您的代码示例,您只需执行以下操作即可使其正常工作:

someData: ['$location', '$q', function ($location, $q) {
                // actual case: use the :id param to fetch data from some service
                // but redirect if it returns false
                return $q.reject();
            }]