【问题标题】:resolve a promise for the MainController解决 MainController 的承诺
【发布时间】:2016-03-26 15:49:14
【问题描述】:

我试图弄清楚如何在创建我的最顶层控制器之前解决一个承诺。我正在使用 ui.router 所以我知道如何为我的不同路由解决控制器的承诺。但我不知道如何在我的第一个控制器加载之前解决它。

这是我的 index.html 的摘录:

<html lang="de" x-ng-app="myapp">
    <body x-ng-controller="MainController">
        ...
        <div id="header" x-ng-include="'top.html'"></div>
        ...
        <div id="viewDiv" ui-view></div>
        ...
    </body>
</html>

我想从服务器加载当前季节(以及其他很少更改的数据),并将其注入到我的 top.html 标头和一些视图控制器的控制器中。我有一项服务可以加载我当前的季节并返回一个承诺:

services.factory('RestAccess', function(Restangular) {
    return {
        loadCurrentSeason : loadCurrentSeason
    };

    function loadCurrentSeason() {
        return Restangular.one('season','current').get();
    }
});

而且我希望将此函数的 RESOLVED 承诺注入到我的 MainController 中:

controllers.controller('MainController', function($scope, currentSeason, SomeService) {
    $scope.season = currentSeason;
    $scope.stuff = SomeService.loadStuff(currentSeason);
});

我该如何配置呢? 这适用于负责 body-element 的 Controller。所以我这里还没有使用任何路由。

我想要类似的东西

resolve: {
    currentSeason : function(RestAccess) {return RestAccess.loadCurrentSeason();}
}

但我不知道该放在哪里。

【问题讨论】:

  • 为什么不等待你的承诺来解决和隐藏内容或用ng-if = "currentSeason" 或类似的东西做任何你想做的事情? loadCurrentSeason.then(function(currentSeason) {$scope.currentSeason = currentSeason; }); 你也可以有一个包装指令来等待承诺,然后通过在一些“init”方法中通过参数给它解析的值来调用控制器。
  • 这不是隐藏内容。这是关于调用需要此参数的服务方法。如果它只是在少数控制器中,我会接受你的建议。但我需要在几十个控制器中使用这个值。
  • 那么你可以让你的服务消耗承诺而不是价值,这就是承诺的想法:将它们作为常规值操作,并在你需要它们的值时注册then。或者,如果这一季的内容非常具体,您甚至可以在启动应用程序之前先加载它,然后使用 angular.bootstrap(...) 启动编译
  • 我的问题是我需要等待所有 3-4 个承诺才能继续。这会使代码变得非常复杂和不可读。我不知道 angular.bootstrap(...),我想这将是我在问这个问题时一直在寻找的直接答案。我决定走另一条路,将我的 MainController 包含到我的 ui.router 状态中。
  • 那么实际上你想在top.html上先加载初始化一些静态数据,然后再为不同的控制器重用?

标签: javascript angularjs angular-promise


【解决方案1】:

您可以为 abstract parent 状态进行解析,该状态将在单独的具体子路由解析之前解析(因此可以在这些解析中使用 ) .

例子:

//In module.config()...
...
$stateProvider
.state('home', {
    url:'/',
    template: '<div ui-view></div>',
    abstract: true,
    resolve: {
        'parentResolve':['yourService', function(yourService){ /*Return promise*/ }]
    }
})
.state('home.child', {
    url:'/child',
    template: '<div>After home</div>',
    controller: ['parentResolve', function(parentResolve){ /*Use parentresolve*/ }],
    resolve: {
        'childResolve':['parentResolve','yourService', function(parentResolve, yourService){ /*Parent resolve is available, as is service*/ }]
    }        
}
...

此外,您可以在尝试加载任何状态之前使用module.run() 运行某些内容。

【讨论】:

  • 目前,我的 MainController 的视图在 $stateProvider 的配置之外。我想我需要为您的解决方案更改它?
  • 是的,我会这样做。一般来说,在外面有一个总体的、无状态的部分很好,但在这种情况下,Angular 在config 中有你需要的东西,你仍然可以表示它不属于一个特定的状态,所以我不不要认为你真的在妥协任何事情。
  • 我将路由更改为您的建议,并带有抽象的主状态。它工作正常,除了一件事:当我尝试解析我的 childResolve 时,parentResolve 没有被解析(但它被正确地注入到控制器中)。当我调试它时,它是未定义的。不过我有一个解决方法。
  • 如果您不介意我问,您有什么解决方法?你介意张贴你有什么和你想出什么吗?给出一个需要被破解才能工作的答案我会觉得很糟糕,所以也许我可以改进它。
  • 我让它休息了一天,现在在子控制器的resolve函数中解析了父级。不知道为什么。解决方法不值得一提。
【解决方案2】:

在路由配置中使用解析

.state('someState',{
   url:'....',
   controller:'MainController',
   resolve:{
      currentSeason:function(SomeService){
         // return the promise needed to resolve for injected variable
         return SomeService.someMethod();
      }
   }

})

我想这就是你要问的。问题有点模糊

【讨论】:

  • 这对我的 index.html 有效吗? (我编辑了问题以使其更清晰)
  • 不...您在原始问题之外留下了太多信息。
【解决方案3】:

先生。复活节兔子,

我有一个非常相似的困境。顺便说一句,问题不是您想在控制器加载之前解决承诺,而是您想在页面加载之前解决承诺,以防止呈现无数据页面。

我的解决方案

  1. 第一步。在承诺解决之前,您不想加载页面/模板。意思是,直到有数据要显示。为此使用ngIf,而不是ngShow,因为“ngIf”只会在我们的条件为真时呈现页面,即存在数据时。

  2. 让 'MainController' 维护一个变量,该变量指示数据是否已加载(意味着承诺已解决),并让 ngIf 监视该变量。

为此,创建一个服务(或服务模型——无论你想怎么称呼它)来保存 Promise 返回的数据。

angular('app').factory('dataServiceModel', function(){

   var dataModel= this;

   var dataModel.someData = {};

   return dataModel;
});

在控制器中,在 promise 回调函数中填充数据并设置变量让 ngIf 知道有数据要显示。

angular('app').controller('MainController', ['dataServiceModel'], function(){

var mainController = this;

mainController.loadedData = false;

mainController.getTheDataFromTheServer(){
      ... 
      ...
      { // Callback to the promise and on successful retrieval
        dataServiceModel.someData = ... the data ..
        mainController.loadedData = true
      }
   }
}); 

现在来自标记;

<ANY ng-controller="MainController as mainController"
  ng-if="mainController.loadedData">
...
</ANY>

我认为这也可能对你有用。

【讨论】:

  • 这与显示无关。这是关于控制器代码运行的。对于每个控制器,我需要加载 5-8 个非常静态的数据(来自服务器)的子集,然后才能将这些数据值用作后续查询的参数。在我开始工作之前,我不想对每个控制器进行编程以等待 3-4 个承诺全部解决。我希望它们以已解决的状态注入控制器。
猜你喜欢
  • 2015-06-24
  • 2018-04-02
  • 2019-09-29
  • 1970-01-01
  • 2020-03-16
  • 2022-12-05
  • 2022-01-22
  • 2018-03-19
  • 1970-01-01
相关资源
最近更新 更多