AnglarJSを使ってアプリケーションを構築する際に発生した問題と解決策(バージョンは1.3.9)


最近会社でAnglarJS(1.3.9)を使って一つのプロジェクトを完成しました.ここで問題と解決策を記録します.$httpサービスを使用してajax要求を送信した場合、バックエンドは判断できない.要求はXMLHttpRequestである.
問題およびシーン:バックエンドは、要求中のheaderX-Requested-Withフィールドを読み取って、フロントエンドの要求が非同期要求XMLHttpRequestであるかどうかを判断し、$httpサービスを使用して要求を送信した場合、バックエンドはfalseと判断することがある.
理由:'X-Requested-With' : 'XMLHttpRequest'は標準のheaderコンテンツではないので、Anglarはheaderにおいてデフォルトでこのフィールドを設定しない.
解決策:$httpProviderに手動でフィールドを設定します.コードは以下の通りです.
    $httpProvider.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
ノート:公共サービスを作成することができます.この変更を配置方法で行うと、各moduleに公共サービスが注入されます.$http.post()メソッドを使用するとパラメータのタイプが正しくありません.
問題とシーン:anglarで$http.post()方法でデータを提出すると、バンドパラメータはForm Dataではなく、JSONオブジェクトであることが分かり、サーバーが一般的な方法でパラメータを正確に取得できなくなり、jQueryの$.post()方法を使って正しく取得することができます.
理由:両者のpostはheaderに対して処理が異なり、jQueryはJSONの対象となるmyDataをプログレッシブ化しています.
    var myData = { a : 1, b : 2 };
    // jQuery post      myData      :"a=1&b=2"
angglarは明らかにこの処理をしていません.
解決策:Anglarの$httpProviderのデフォルトの処理を修正します.コードは以下の通りです.
    $httpProvider.defaults.transformRequest = function(obj){
        var str = [];
        for(var p in obj) {
            str.push(encodeURIComponent(p) + '=' + encodeURIComponent(obj[p]));
        }
        return str.join("&");
    };

    $httpProvider.defaults.headers.post = {
        'Content-Type': 'application/x-www-form-urlencoded'
    };
ノート:同じように公衆サービスでこの修正をすべきです.$scope.$apply(fn)を呼び出して、表示時報エラーを更新します.
問題およびシーン:scope上のmodelデータを更新するとき、$rootScope:inprogで傍受した場合、ビューは自動的に更新されていないことが分かり、手動でdigestを呼び出してビューの更新を通知するが、エラーが発生することがある.
原因:このエラーの原因は、プロセス中に$scope.$apply(fn)が実行中であり、これに基づいてこの方法を繰り返し起動することができないからです.
ソリューション:この方法を呼び出した時にセキュリティチェックができます.パッケージコードは以下の通りです.
    $scope.safeApply = function(fn) {
        var phase = this.$root.$$phase;
        if (phase === '$apply' || phase === '$digest') {
            if (fn && (typeof(fn) === 'function')) {
                fn();
            }
        } else {
            this.$apply(fn);
        }
    };
ノート:$rootScope:inprog変数は$scope.$apply(fn)の内部属性であり、$$phaseまたはscopeであれば、プロセス中にnullの方法が実行されていないということを示しています.そうでなければ直接に起動できます.
統一ブロックを追加してajaxに対する要求またはリターン処理を行います.
問題とシーン:私が遭遇したシーンは非同期要求を送信する時、バックエンドは先にユーザがログインしたかどうかを判断します.登録していない場合はundefined$applyresponseフィールドを追加します.フロントエンドはこのフィールドコントロールページを読み取り、このurlにジャンプします.私が最初に思い付いた解決策はフロントエンドが同じブロックを作る必要があります.非同期要求のすべてのheaderをブロックする.
解決策:Anglarの中のredirecturl部分のソースコードの注釈を見て、ブロックの書き方をいくつか発見しました.私が選んだのは下記の通りです.
    *   // register the interceptor as a service
    *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
    *     return {
    *       // optional method
    *       'request': function(config) {
    *         // do something on success
    *         return config;
    *       },
    *
    *       // optional method
    *      'requestError': function(rejection) {
    *         // do something on error
    *         if (canRecover(rejection)) {
    *           return responseOrNewPromise
    *         }
    *         return $q.reject(rejection);
    *       },
    *       // optional method
    *       'response': function(response) {
    *         // do something on success
    *         return response;
    *       },
    *
    *       // optional method
    *      'responseError': function(rejection) {
    *         // do something on error
    *         if (canRecover(rejection)) {
    *           return responseOrNewPromise
    *         }
    *         return $q.reject(rejection);
    *       }
    *     };
    *   });
    *   $httpProvider.interceptors.push('myHttpInterceptor');
responseをブロックしたコードは以下の通りです.
    commonService.factory('redirectInterceptor', function(){
        return {
            'response': function(response) {
                if(response.headers().redirecturl) {
                    window.location.href = response.headers().redirecturl;
                }
                return response;
            }
        };
    });

    $httpProvider.interceptors.push('redirectInterceptor');
ノート:最後の行は、$httpProviderのブロックにブロックを登録することを示し、同様に、パブリックサービスの構成方法に記載すべきである.response間の通信問題
問題およびシーン:2つのビューがそれぞれ2つの$httpProviderによって制御されている場合、そのうちの1つのビューが変化していることを、他のビューに通知する必要があります.
解決策:総じて言えば、Anglarにおけるコントローラ通信には3つの処理方法があります.
  • は、スコープ継承方式、すなわち、親コントローラの内容をサブコントローラで継承する.
  • は、イベントに基づく方法、すなわちcontrollercontroller$onの3つの方法である.
  • サービス方式は、サービスの一例を書き込み、注入によって使用される.
  • 最後の方法を選択しました.コード例は以下の通りです.
        //JS
        var app = angular.module('myApp', []);
        app.factory('instance', function(){
            return {};
        });
        app.controller('MainCtrl', function($scope, instance) {
            $scope.change = function() {
            instance.name = $scope.test;
            };
        });
        app.controller('sideCtrl', function($scope, instance) {
            $scope.add = function() {
                $scope.name = instance.name;
            };
        });
        //html
        
    click me
    my name
    note:Anglarでのサービスは一例ですので、サービスでオブジェクトを生成し、このオブジェクトは依存注入によってすべてのコントローラで共有できます.クリックによって変化が生じない場合は、$emit方法と併せて通信することもできる.他の2つの方法は駅構内記事を参照することができます.アングラーJSコントローラコントローラコントローラコントローラコントローラコントローラコントローラコントローラコントローラコントローラはどうやって通信しますか?
    おわりに
    以上は私のためにアングラーの応用を編纂する時出会った問題と解決案で、記録して共有してきました.皆さんのご指摘を歓迎します.