web-dev-qa-db-ja.com

angular ui-routerでの依存関係解決順序の約束

プロミス(Configファクトリによって返された)が正常に解決されたときにのみインスタンス化されるトップレベルのコントローラーをセットアップしました。その約束は基本的に、RESTfulエンドポイントなどを使用して、Webアプリ構成をダウンロードします。

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

この設定により、下位のコントローラーが使用する前に、構成が適切にロードされていることを確認できます。

次に、より深くネストされたコントローラーに、factoryを使用し、解決された場合にのみ機能する別のConfigを注入する必要があります(Webを必要とする_$resource_ラッパーのように見える)サービスURL)。私が行った場合:

_$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_の解決が停止し(Errorsをスローすることさえありませんが、これは別の問題です)、Configがトップレベルのコントローラーによって初期化されることはありません

_ui-router_が依存関係を逆の順序で解決するのはなぜですか? TheResourceオブジェクトをどのように簡単に解決できますかafterトップレベルMainCtrlConfigを解決しました(_$inject_に依存せずに、もちろん)?

[〜#〜] update [〜#〜]this plnkr's log から、ネストされたコントローラーの後にのみ、最上位のresolveが試行されていることがわかります独自の解決プロセスを開始しました。

19
frapontillo

@Kasper Lewauの回答と同様に、単一の状態の解決に対する依存関係を指定できます。解決の1つが同じ解決ブロックの1つ以上の解決プロパティに依存している場合。私の場合、checkSは他の2つの解決策に依存しています

.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の内部動作の詳細については、 次のドキュメント の「解決」セクションを確認してください。

60

解決オブジェクトは並行して実行されるため、特定の階層に従いません。ただし、高次の解決オブジェクトを2次解決への依存関係として定義することにより、ネストされた解決が可能です。

$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!'. 
      }]
    }
  });

一種の悪い例ですが、私はあなたがそれの要点を得ると思います。上位レベルの解決オブジェクトの名前を下位レベルの解決への依存関係として定義すると、最初に解決されるまで待機します。

これは、低次のオブジェクトを解決する前に特定のデータをプリロードする方法と、認証要件(特に)を解決した方法です。

幸運を。

16
Kasper Lewau

私は決議が連鎖すべきであることに同意します、そして私はこの領域の周りで多くの問題にぶつかりました。

しかし、そうではないので、私が思いついた解決策は、データが完成したときに解決するサービスに格納されている自分のプロミスを使用することです。私はあなたの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();
    });
});

最後の最も重要なステップは、上記の約束が解決されるまで、2番目の子をresolves関数のコンテンツと呼ばないことです。

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

あなたが知っておく必要がある主なことは、設定が状態に保存されていることです。これを回避する方法はあるはずですが、これは以前に行った方法です。

1
Josh

連鎖させることはできませんが、別のものから呼び出すことができます。

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