angularjsサービスに入る$ HTTPからのデータを1回だけ呼び出す/キャッシュする

StackOverflow https://stackoverflow.com//questions/24054024

質問

これは本当に単純/ばかな質問のように聞こえるかもしれませんが、私は私が前にこのシナリオに遭遇していないのでそれを尋ねる必要があります...大丈夫私は私のAngularjsアプリでサービスを持っています。このサービスは現在、すべて同じ機能/コードを80%実行する4つのメソッドを含み、これをより効率的にしたいと思います。これが私のサービスがどのように見えるか(コードが削除された状態で)次のようになります:

    .factory('townDataService', function ($http) {

        var townList = {};

        townList.getTownList = function () {

            return $http({method: 'GET', url: '/api/country/cities'})
                .then(function (response) {

                    // HERE WE FORMAT THE response as desired... that creates a returnArray
                    var returnArray = [];
                    // loop through the countries
                    var JsonData = response.data;

                    for (key in JsonData['countries']) {
                         // formatting code...
                    }
                    // end of repeated CODE

                    return returnArray; // this is array, we don't do any formatting here

                });
        };


     townList.getCurrentTown = function (place) {

            return $http({method: 'GET', url: '/api/country/cities'})
                .then(function (response) {

                    // HERE WE FORMAT THE response as desired... that creates a returnArray
                    var returnArray = [];
                    // loop through the countries
                    var JsonData = response.data;

                    for (key in JsonData['countries']) {
                         // formatting code...
                    }
                    // end of repeated code

                    // now the format further / work with the returnArray...
                    for (var i = 0; i < returnArray.length; i++) {
                        // do stuff
                    }
                    return currentTown; // this is a string

                });
        };


        townList.getCurrentCountry = function (place) {

            return $http({method: 'GET', url: '/api/country/cities'})
                .then(function (response) {

                    // HERE WE FORMAT THE response as desired... that creates a returnArray
                    var returnArray = [];
                    // loop through the countries
                    var JsonData = response.data;

                    for (key in JsonData['countries']) {
                         // formatting code...
                    }
                    // end of repeated code

                    // now the format further / work with the returnArray...
                    for (var i = 0; i < returnArray.length; i++) {
                        // do stuff
                    }
                    return currentCountry; // this is a string

                });
        };

        return townList;

    }
)
;
.

オブジェクト配列または文字列を返す前に、各メソッドの同じ$http 'GET'と同じフォーマットコード(たくさんのネストループ)を繰り返します。これは効率的なものからはかけ離れています!この機能をそれ自身の機能にするための最善の方法は何ですか。それで私たちは1回の取得URLを呼び出すだけでなく、それでも各メソッドで約束を返しますか?必要に応じてデータをフォーマットする前に、$http({method: 'GET', url: '/api/country/cities'})の結果をVarとして設定して各メソッドに挿入/渡す必要がありますか?一般的な$cacheFactoryを使用する必要がありますか?

これが愚かな質問であればすみません、私は自分自身をよく説明していないならば、私は質問を言い換えなければならない。

事前にありがとうございました。

役に立ちましたか?

解決

あなたが言うのと同じくらいです。このコードは(そして多くの方法で)リファクタリングすることができます。一例:

HTTPのものを別のサービスに率いて、キャッシングの世話をするでしょう。(これに関するもう1つの考えは、HTTP /リモートコールのためのサービスを提供することです。これは一般的な使用デコレータであります。別の方法:

リモートコールサービス:

.service('townHttpService', function($http, $q) {
    var cache;

    function getCities() {
        var d = $q.defer();
        if( cache ) {
            d.resolve(cache);
        }
        else {
            $http({method: 'GET', url: '/api/country/cities'}).then(
                function success(response) {
                    cache = response.data;
                    d.resolve(cache);
                },
                function failure(reason) {
                    d.reject(reason);
                }
            });
        }
        return d.promise;
    }

    function clearCache() {
        cache = null;
    }

    return {
        getCities: getCities,
        clearCache: clearCache
    };
})
.

フォーマッター:

.service('townFormatter', function() {
    return function townFormatter(jsonData) {
        // HERE WE FORMAT THE response as desired... that creates a returnArray
        var returnArray = [], key;
        // loop through the countries
        for (key in jsonData['countries']) {
             // formatting code...
        }
        // end of repeated CODE
        return returnArray; // this is array, we don't do any formatting here
    };
})
.

上記の観点から書かれたあなたのtownDataService

.factory('townDataService', function (townHttpService, townFormatter) {

    var townList = {};

    townList.getTownList = function () {
        return townHttpService.getCities().then(townFormatter);
    };

    townList.getCurrentTown = function (place) {
        return townHttpService.getCities().then(townFormatter).then(function(cityList) {
            var currentTown;
            for (var i = 0; i < cityList.length; i++) {
                // do stuff
            }
            return currentTown; // this is a string
        });
    };

    townList.getCurrentCountry = function (place) {
        return townHttpService.getCities().then(townFormatter).then(function(cityList) {
            var currentCountry;
            for (var i = 0; i < cityList.length; i++) {
                // do stuff
            }
            return currentCountry; // this is a string
        });

    return townList;
})
.

他のヒント

私はあなたが2つの質問を得たと思います繰り返しの論理と結果をキャッシュするための最良の方法を取り除くと思います。

最初の - 重複コードの削除: townList.getTownListは一般的な方法です。他の2つの方法はこのメソッドの拡張です。 だから、

townList.getCurrentTown = function(place) {
  var towns = townList.getTownList();
  for (var i = 0; i < returnArray.length; i++) { //additional stuff
  }
  return currentTown;
};


townList.getCurrentCountry = function(place) {
  var towns = townList.getTownList();
  for (var i = 0; i < returnArray.length; i++) { //additional stuff
  }
  return currentCountry;
};
.

2次キャッシング値 これで、呼び出しはtownList.getTownListでのみ行われている場合、キャッシュへのロジックはここで簡単に実装できます。ただし、これは、データがOneTime Fetchかどうかによって異なります。 ワンタイムフェッチ: HTTP呼び出しのキャッシュを有効にする$http({method: 'GET', url: '/api/country/cities', cache:true});

リクエストに基づくリフレッシュ:私は、データを更新するかどうかを知らせるためにrefresh変数を渡します。したがって、更新が真の場合、またはタウンリストが空の場合、データは取得されます。

var srvc = this;
var townList;
townList.getTownList = function(refresh ) {
  if (refresh || !townList) {
    srvc.townList = $http({
      method: 'GET',
      url: '/api/country/cities'
    })
      .then(function(response) {
        var returnArray = [];
        var JsonData = response.data;
        for (var key in JsonData.countries) {}
        return returnArray; // this is array, we don't do any formatting here
      });
  }

  return townList;
};
.

あなたができることを特別なものはありません。コードの重複を避け、読みやすさの向上を避けるために、Get応答とリファクタリングをビットにキャッシュする必要があります。

.factory('townDataService', function ($http) {
    var getCitiesAsync = function(){
        return $http({method: 'GET', url: '/api/country/cities', cache:true});
    };

    var townList = {};

    townList.getTownList = function () {
        return getCitiesAsync().then(prepareTownList);
    };

    var prepareTownList = function(response){
        //extract towns and do whatever you need
        return result;
    };

    ...
.

$ CacheFactoryを使用するためのもの - このような単純なシナリオのオーバーヘッドのようです。内蔵キャッシュオプションを使用するだけです。

タイミングの問題を回避するために、解決策を少し延ばすのがおそらく良い:

function getCities() {
        var d = $q.defer();
        if( cache ) {
            d.resolve(cache);
        }
        else {
            $http({method: 'GET', url: '/api/country/cities'}).then(
                function success(response) {
                    if (!cache) {
                        cache = response.data;
                    }
                    d.resolve(cache);
                },
                function failure(reason) {
                    d.reject(reason);
                }
            });
        }
        return d.promise;
    }
.

(おそらく2番目または3番目の)WebServiceへの呼び出しが成功した後、サーバーの応答を待っている間にキャッシュ変数が設定されているかどうかを確認します。もしそうなら、すでに割り当てられた値を返すことができます。そのように、複数の呼び出しが発行された場合、変数cacheへの新しい割り当てはありません。

function success(response) {
    if (!cache) {
        cache = response.data;
.

問題を解決する必要はありませんが、(データバインディングを使用する場合など)、データを1回取得することは必ず最適です。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top