AngularJSを使用したグローバルAjaxエラーハンドラー


82

私のウェブサイトが100%jQueryだったとき、私はこれを行っていました:

$.ajaxSetup({
    global: true,
    error: function(xhr, status, err) {
        if (xhr.status == 401) {
           window.location = "./index.html";
        }
    }
});

401エラーのグローバルハンドラーを設定します。今、私はangularjsを使用$resourceして$http、サーバーへの私の(REST)要求を行うこと。同様にAngularでグローバルエラーハンドラーを設定する方法はありますか?


AngularJS Failed Resource GETの重複の可能性はありますか?
MilkyWayJoe 2012

1
いいえ、アプリケーションに対してグローバルエラー401ハンドラーを実行します
cricardol 2012

笑、あなたはあなたが望むものを考えましたが、異なるhttpステータス(あなたは変更することができます)を持っていますか?とにかく、pkozlowski.opensourceの答えはそれを行う方法を示しています
MilkyWayJoe

いいえ、それはジャステンの答えに非常に似ています...これはあなたが話している質問と重複していません
クリカルドール2012

回答:


97

また、Angularを使用してWebサイトを構築していますが、グローバルな401処理でこれと同じ障害に遭遇しました。このブログ投稿に出くわしたとき、私はhttpインターセプターを使用することになりました。多分あなたはそれが私がしたのと同じくらい役に立つと思うでしょう。

「AngularJS(または同様の)ベースのアプリケーションでの認証。」espeoソフトウェア

編集:最終的な解決策

angular.module('myApp', ['myApp.filters', 'myApp.services', 'myApp.directives'], function ($routeProvider, $locationProvider, $httpProvider) {

    var interceptor = ['$rootScope', '$q', function (scope, $q) {

        function success(response) {
            return response;
        }

        function error(response) {
            var status = response.status;

            if (status == 401) {
                window.location = "./index.html";
                return;
            }
            // otherwise
            return $q.reject(response);

        }

        return function (promise) {
            return promise.then(success, error);
        }

    }];
    $httpProvider.responseInterceptors.push(interceptor);

4
$ q.reject(response);を返す必要があります。status == 401の場合、ノイズの多い角度エラーを回避するため
s_t_e_v_e 2013

1
@daniellmb。場合によります。ビューを変更するだけでなく、実際に別のページに移動したい場合は、実際には$ windowを使用する必要があります。ログインページがAngularを使用した別のビューとコントローラーである場合は、$ location.path
uriDium 2013年

1
@uriDium正しい私のポイントは、モックとテストができるように、角度の付いたオブジェクトを使用することでした。
daniellmb 2013年

22
$ httpProvider.responseInterceptorsは非推奨になりました。docs.angularjs.org/api/ng.$http#description_interceptorsを参照してください。
quartzmo

1
成功すると、次のように戻る必要があります return response || $q.when(response);、応答が空の場合にpromiseオブジェクトもように、の。
Ashish Gaur

77

responseInterceptorsはAngular1.1.4で非推奨になっていることに注意してください。以下に、公式ドキュメントに基づく抜粋を示し、インターセプターを実装する新しい方法を示します。

$provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
  return {
    'response': function(response) {
      // do something on success
      return response || $q.when(response);
    },

   'responseError': function(rejection) {
      // do something on error
      if (canRecover(rejection)) {
        return responseOrNewPromise;
      }
      return $q.reject(rejection);
    }
  };
});

$httpProvider.interceptors.push('myHttpInterceptor');

これは、Coffeescriptを使用した私のプロジェクトでどのように見えるかです。

angular.module("globalErrors", ['appStateModule']).factory "myHttpInterceptor", ($q, $log, growl) ->
  response: (response) ->
    $log.debug "success with status #{response.status}"
    response || $q.when response

  responseError: (rejection) ->
    $log.debug "error with status #{rejection.status} and data: #{rejection.data['message']}"
    switch rejection.status
      when 403
        growl.addErrorMessage "You don't have the right to do this"
      when 0
        growl.addErrorMessage "No connection, internet is down?"
      else
        growl.addErrorMessage "#{rejection.data['message']}"

    # do something on error
    $q.reject rejection

.config ($provide, $httpProvider) ->
  $httpProvider.interceptors.push('myHttpInterceptor')

ただし、responseErrorインターセプターにはxhrデータやその他の有用な情報はありません。それが回復可能かどうかを判断することさえ不可能です。
zw0rk 2013年

1
@ zw0rkあなたは...中にresponseErrorrejectionあなたが必要とするすべてを持っています。
ラングドン

その最後の行$httpProvider...は、config()ブロックに包まれていますか?
デルウィン2014

実際、Coffeescriptを使用してプロジェクトでどのように行ったかを示すために、回答を編集しました。Javascriptで使用したい場合は、js2coffee.orgを使用してください。
MikeR 2014

関数のresponse下でのすべての参照がresponseError実際に参照であるrejection必要はありません(または、パラメーターの名前を次のように変更する必要がありますresponseか?
Adam Nofsinger 2014年

16

<script type="text/javascript" src="../js/config/httpInterceptor.js" ></script>次の内容でファイルを作成します。

(function(){
  var httpInterceptor = function ($provide, $httpProvider) {
    $provide.factory('httpInterceptor', function ($q) {
      return {
        response: function (response) {
          return response || $q.when(response);
        },
        responseError: function (rejection) {
          if(rejection.status === 401) {
            // you are not autorized
          }
          return $q.reject(rejection);
        }
      };
    });
    $httpProvider.interceptors.push('httpInterceptor');
  };
  angular.module("myModule").config(httpInterceptor);
}());

@ThilakRaj上記のコードは、すべてのhttpリクエストで実行する必要があります。そのため、Chromeで2つのブレークポイントを作成します。1つは「returnresponse」行に、もう1つは「return $ q.reject」に作成して、正常に実行されることを確認します。
ヤン・テリエ・ソーレンセン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.