簡體   English   中英

承諾角度ui-router中的依賴關系解析順序

[英]Promise dependency resolution order in angular ui-router

我已經設置了一個頂級控制器,只有在成功解析了一個promise(由Config工廠返回)時才會實例化。 該承諾基本上下載了Web應用程序配置,使用RESTful端點等。

$stateProvider
  .state('app', {
    url: '/',
    templateUrl: 'views/_index.html',
    controller: 'MainCtrl',
    resolve: {
      config: 'Config'
    }
  });

此設置允許我在任何較低控制器有機會使用之前斷言配置已正確加載。

現在我需要在更深層次的嵌套控制器中注入另一個使用Config factory ,並且僅在解析時工作(將其視為需要一些Web服務URL的$resource包裝器)。 如果我做:

$stateProvider
  .state('app.bottom.page', {
    url: '/bottom/page',
    templateUrl: 'views/_a_view.html',
    controller: 'BottomLevelCtrl',
    resolve: {
      TheResource: 'MyConfigDependingResource'
    }
  });

看起來resolve評估順序不是從上到下跟隨控制器層次結構,而是從下到上,因此:

  1. 輸入app.bottom.page
  2. ui-router嘗試解析MyConfigDependingResource ,但注入失敗,因為Config從未被初始化
  3. ui-router解決方案由於錯誤而停止(甚至沒有拋出Error ,但這是另一個問題),並且Config永遠不會被頂級控制器初始化

為什么ui-router以相反的順序解析依賴關系? 在頂級MainCtrl解析Config 之后如何輕松解析我的TheResource對象(當然不依賴$inject )?

更新 :從這個plnkr的日志 ,你可以看到,頂層resolve嵌套的控制器已經開始了自己的解析過程后,才嘗試。

與@Kasper Lewau的答案類似,可以指定對具有單個狀態的結算的依賴性。 如果其中一個解析依賴於同一解析塊中的一個或多個解析屬性。 在我的情況下, checkS依賴於另外兩個結果

.state('stateofstate', {
    url: "/anrapasd",
    templateUrl: "views/anrapasd.html",
    controller: 'SteofsteCtrl',
    resolve: {
        currU: function(gamMag) {
            return gamMag.checkWifi("jabadabadu")
        },
        userC: function(gamUser, $stateParams) {
            return gamUser.getBipi("oink")
        },
        checkS: ['currU', 'userC', 'gamMag', function(currU, userC, gamMag) {
            return gamMag.check(currU, userC);
        }]
    }
})

** PS:**查看以下文檔的“解決”部分,了解有關resolve內部工作的更多詳細信息。

解析並行運行的對象,因此不遵循特定的層次結構。 但是,通過將更高階的解析對象定義為對輔助解析的依賴關系,可以實現嵌套解析。

$stateProvider
  .state('topState', {
    url: '/',
    resolve: {
      mainResolveObj: ['$someService', function ($someService) {
        return 'I am needed elsewhere!';
      }]
    }
  })
  .state('topState.someOtherState', {
    url: '/some-other-place',
    resolve: {
      someOtherResolveObj: ['mainResolveObj', function (mainResolveObj) {
        console.log(mainResolveObj); //-> 'I am needed elsewhere!'. 
      }]
    }
  });

這是一個糟糕的例子,但我認為你得到了它的要點。 將更高級別的解析對象的名稱定義為對較低級別解析的依賴關系,它將等待它首先解析。

這就是我們如何在低階解析對象之前解決預加載某些數據的問題,以及身份驗證要求(以及其他事項)。

祝好運。

我同意你的意見,結果應該鏈接,我在這個領域遇到了很多問題。

但是,他們沒有,所以我提出的解決方案是使用我自己的承諾存儲在您在數據完成時解決的服務中。 我盡力編輯你的plunkr工作但無濟於事。 我不再遇到你的錯誤,所以希望你能從中解決這個問題: http//plnkr.co/edit/Yi65ciQPu7lxjkFMBKLn?p = preview

它正在做什么:

將配置存儲在與新promise對象一起的狀態中

myapp.service('state', function($q) {
  this.load = $q.defer();
  this.config = {}
})

在您第一次解決時,將您的配置存儲在此服務中,並在准備好后解決我們在上面創建的新承諾。

myapp.factory('Config', function($http, $log, state) {
  return $http.get('example.json')
    .then(function (data) {
      angular.extend(state.config, data.data);
      state.load.resolve();
    });
});

最后也是最重要的一步是在我們的上述承諾得到解決之后,不要將我們的第二個內容稱為子解析函數:

myapp.factory('MyConfigDependingResource', function($log, state) {
  return state.load.promise.then(function() {
    if (!state.config.text) {
      $log.error('Config is uninitialized!');
    }
    else {
      // Do wonderful things
    }
    return
  });
});

您需要注意的主要事情是配置現在存儲在一個狀態中。 應該有辦法解決這個問題,但這就是我以前做過的事情。

雖然它們無法鏈接,但您可以從另一個中調用:

var resolve2 = ['$stateParams',function($stateParams){
  // do resolve 2 stuff
  ...
  return true;
}];

var resolve1 = ['$stateParams',function($stateParams){
  // do resolve 1 stuff
  ...
  // now do resolve2 stuff
  return $injector.invoke(resolve2,this,{$stateParams:$stateParams});
}];


$stateProvider.state("myState", {
  resolve: {
    resolve1: resolve1
  }
});

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM