3

これで、javascript の実行方法から、すべてのリモート リクエストを同期ではなく非同期で実行することをお勧めすることがわかりました。私はその 99% の時間に同意しますが、リモート リクエストを非同期ではなく同期として実行したい場合があります。たとえば、セッション データの読み込みは、そのデータが読み込まれるまでビューをレンダリングしたくないため、同期的に行いたいと考えています。このプランカーは、セッション データを非同期にロードする際の問題を示しています (注: $timeout を使用して、非同期呼び出しで何が起こるかをシミュレートしています)。

http://plnkr.co/edit/bzE1XP23MkE5YKWxRYrn?p=preview

data プロパティは、データを取得しようとしたときにデータが使用できないため、何もロードしません。data2 は、データを取得しようとしたときにデータが使用可能であるという理由だけでロードします。この場合、セッション変数をスコープに配置するだけで完了できますが、常にそうであるとは限りません。

jQuery の .ajax() メソッドを使用する以外に、Angular アプリケーションでリモート呼び出しを同期するより良い方法はありますか (できるだけ jQuery に依存しないようにします)。

4

3 に答える 3

7

コントローラーをロードする前にセッション データをロードする場合は、それをパラメーターとして含める必要がありresolveます ( を使用していると仮定します$routeProvider)。

例えば:

angular.module('mymodule', ['ngResource'])

  /* here's our session resource.  we can call Session.get() to retrieve it. */
  .factory('Session', ['$resource', function($resource) {
     return $resource('/api/session.json');
   }])

  /* here's our controller + route definition. */
  .config(['$routeProvider', function($routeProvider) {

    $routeProvider.when('/foo', {
      controller: 'MyCtrl',
      templateUrl: '/templates/foo.html',

      /* the controller will not be loaded until the items
       * below are all resolved! */
      resolve: {
        session: ['$q', 'Session', function($q, Session) {
          var d = $q.defer();
          Session.get(function(session) {
            /* session returned successfully */
            d.resolve(session);
          }, function(err) {
            /* session failed to load */
            d.reject(err);
          });
          return d.promise;
        }]
      }
    });
  }])

  .controller('MyCtrl', ['$scope', 'session', function($scope, session) {
    /* 'session' here is the key we passed to resolve above.
     * It will already be loaded and resolved before this function is called */
    $scope.session = session;
  }]);
于 2013-07-18T19:47:35.497 に答える
-1

より良い解決策は、応答インターセプターを追加することです。

checkAuth = ($q, $location) ->
  success = (response) ->
    response
  error = (response) ->
    errorCode = response.status
    $location.path '/login' if errorCode is 403 or errorCode is 401
    # $q.reject response - no need because we are redirecting before any other promises in the chain will resolve (were breaking our future promises)

  (promise) ->
    promise.then success, error

$httpProvider.responseInterceptors.push checkAuth

そして、あなたの $routeProvider、または私の場合は $stateProvider で:

.state 'user',
  templateUrl: 'assets/views/user/partials/user.html'
  resolve:
    credentials: (checkLogIn) ->
      checkLogIn.get().$promise

checkLogIn.get() の promise が拒否されると (エラー ハンドラが起動されます)、それが 401 または 403 応答 (未認証または無許可) であると想定すると、promise チェーンが壊れ、ユーザーは /login に「リダイレクト」されます。

このメソッドを使用すると、ルートごとにエラーを処理する代わりに、エラー呼び出しがインターセプターに送られます。

于 2014-03-07T07:30:07.547 に答える