Javascript ui路由器:templateUrl函数中的异步数据

Javascript ui路由器:templateUrl函数中的异步数据,javascript,angularjs,angular-ui-router,promise,angular-promise,Javascript,Angularjs,Angular Ui Router,Promise,Angular Promise,我在ui路由器方面遇到了一个相当新颖的问题。我基本上是试图在API中查询模板url,该url作为资源对象存储和返回。问题在于templateUrl函数似乎返回为未定义。我的代码如下: (function() { 'use strict'; angular.module('myApp') .config(function ($stateProvider, PageProvider, $httpProvider) { $stateProvider .

我在ui路由器方面遇到了一个相当新颖的问题。我基本上是试图在API中查询模板url,该url作为
资源
对象存储和返回。问题在于
templateUrl
函数似乎返回为未定义。我的代码如下:

(function() {
    'use strict';

  angular.module('myApp')
    .config(function ($stateProvider, PageProvider, $httpProvider) {
      $stateProvider
        .state('core', {
          abstract: true,
          templateUrl: 'app/core/core.index.html',
          controller: 'CoreController',
          controllerAs: 'vm'
        })
        /* Parent page view */
        .state('core.page', {
          url: '/:slug',
          views: {
            'page_content@core': {
              templateUrl: function(params) {
                var slug = params.slug;
                // only need to load core template
                var url = 'assets/templates/' + slug + '.html';

                return url;
              },
              controller: 'PageController',
              controllerAs: 'vm'
            }
          }
        })
        .state('core.page.child', {
          url: '/:child',
          views: {
            'page_content@core': {
              templateUrl: function($stateParams) {
                PageProvider
                  .$get() // $get() returns Page service
                  .findOne($stateParams.child)
                  .$promise
                  .then(function(data){
                    return data.template.url;
                  });
              }
            }
          }
        });
      });
})();
我为我的状态“core.page.child”设置了一个断点,以查看作用域中有哪些变量可用,我发现了一些非常奇怪的事情:

我真的不明白为什么会发生这种情况,因为
.then(cb)
只有在承诺得到解决后才被调用,这意味着它应该像预期的那样返回正确的值,但它没有

任何帮助都将不胜感激

编辑:我应该补充的是,ui路由器根本没有加载我的模板-我得到一个空的
ui视图
。我最初认为我的
$stateProvider
配置可能有问题,但事实似乎并非如此

Edit2:我在调用堆栈的基础上深入研究了源代码。看来你们两个都是对的——ui路由器不符合承诺

/**
 * @ngdoc function
 * @name ui.router.util.$templateFactory#fromConfig
 * @methodOf ui.router.util.$templateFactory
 *
 * @description
 * Creates a template from a configuration object. 
 *
 * @param {object} config Configuration object for which to load a template. 
 * The following properties are search in the specified order, and the first one 
 * that is defined is used to create the template:
 *
 * @param {string|object} config.template html string template or function to 
 * load via {@link ui.router.util.$templateFactory#fromString fromString}.
 * @param {string|object} config.templateUrl url to load or a function returning 
 * the url to load via {@link ui.router.util.$templateFactory#fromUrl fromUrl}.
 * @param {Function} config.templateProvider function to invoke via 
 * {@link ui.router.util.$templateFactory#fromProvider fromProvider}.
 * @param {object} params  Parameters to pass to the template function.
 * @param {object} locals Locals to pass to `invoke` if the template is loaded 
 * via a `templateProvider`. Defaults to `{ params: params }`.
 *
 * @return {string|object}  The template html as a string, or a promise for 
 * that string,or `null` if no template is configured.
 */
this.fromConfig = function (config, params, locals) {
  return (
    isDefined(config.template) ? this.fromString(config.template, params) :
    isDefined(config.templateUrl) ? this.fromUrl(config.templateUrl, params) :
    isDefined(config.templateProvider) ? this.fromProvider(config.templateProvider, params, locals) :
    null
  );
};
看来我要么使用
$stateProvider.decorator
,要么破解ui路由器的核心。我想我可以做后一件事,然后提交一份PR。我也会在github repo上发布这个问题,看看ui路由器团队中是否有人能解决这个问题。

您可以使用
resolve
templateProvider
来执行此操作

  .state('child', {
      url: '/:child',
      resolve: {
        childTemplate: function ($stateParams, $templateRequest) {
          return $templateRequest($stateParams.child + ".html");
        }
      },
      templateProvider: function(childTemplate) { 
        return childTemplate;
      }
  });

这将创建一个解析,该解析使用
$stateParams
获取模板(我使用
$templateRequest
获取、添加到
$templateCache
,并一次返回内容)。然后,解析的模板内容被注入视图的templateProvider。

我不知道
templateUrl
是否可以执行承诺,但如果可以,我认为您至少需要返回此承诺。您是否尝试在
页面提供程序之前添加
return
。$get()…
?@TomekSułkowski是正确的,您不能期望templateUrl函数知道它正在使用承诺,除非您实际返回承诺。“仅限副作用”功能不会等待完成。您的问题与此非常类似。也许这有助于他们使用
templateProvider
。我在ui路由器repo上发布了一个问题。找到解决方案后,我们会给你们两个回复。@AWolf这当然值得一试。一开始我被“必须返回HTML”吓坏了;我想我可以让服务器使用
$http.get
直接静态地提供html文件。谢谢Chris,这似乎是最优雅的解决方案!我不知道
resolve
块中的值被注入
templateProvider
函数。我还想问一下
templateProvider
是否仅在
resolve
块中的所有承诺都已解决时执行?我相信模板提供程序是在解决后调用的。此外,它直到最近才收到解析。谢谢你,克里斯,我将结束回购协议的发行。这非常有帮助。如果我在我的childTemplate resolve中放入超时服务,并在3秒钟后返回一些html字符串,这将不起作用。在这种情况下,我的templateProvider首先被解雇,然后是我的解决方案,这不是我所期望的