AngularJS:ファクトリ$ http.getJSONファイル


84

ハードコードされたJSONファイルだけを使用してローカルで開発したいと考えています。私のJSONファイルは次のとおりです(JSONバリデーターに入れると有効です):

{
    "contentItem": [
            {
            "contentID" : "1", 
            "contentVideo" : "file.mov",
            "contentThumbnail" : "url.jpg",
            "contentRating" : "5",
            "contentTitle" : "Guitar Lessons",
            "username" : "Username", 
            "realname" : "Real name",
            "contentTags" : [
                { "tag" : "Guitar"},
                { "tag" : "Intermediate"},
                { "tag" : "Chords"}
            ],      
            "contentAbout" : "Learn how to play guitar!",
            "contentTime" : [
                { "" : "", "" : "", "" : "", "" : ""},
                { "" : "", "" : "", "" : "", "" : ""}
            ],          
            "series" :[
                { "seriesVideo" : "file.mov", "seriesThumbnail" : "url.jpg", "seriesTime" : "time", "seriesNumber" : "1", "seriesTitle" : "How to Play Guitar" },
                { "videoFile" : "file.mov", "seriesThumbnail" : "url.jpg", "seriesTime" : "time", "seriesNumber" : "2", "seriesTitle" : "How to Play Guitar" }
            ]
        },{
            "contentID" : "2", 
            "contentVideo" : "file.mov",
            "contentThumbnail" : "url.jpg",
            "contentRating" : "5",
            "contentTitle" : "Guitar Lessons",
            "username" : "Username", 
            "realname" : "Real name",
            "contentTags" : [
                { "tag" : "Guitar"},
                { "tag" : "Intermediate"},
                { "tag" : "Chords"}
            ],      
            "contentAbout" : "Learn how to play guitar!",
            "contentTime" : [
                { "" : "", "" : "", "" : "", "" : ""},
                { "" : "", "" : "", "" : "", "" : ""}
            ],          
            "series" :[
                { "seriesVideo" : "file.mov", "seriesThumbnail" : "url.jpg", "seriesTime" : "time", "seriesNumber" : "1", "seriesTitle" : "How to Play Guitar" },
                { "videoFile" : "file.mov", "seriesThumbnail" : "url.jpg", "seriesTime" : "time", "seriesNumber" : "2", "seriesTitle" : "How to Play Guitar" }
            ]
        }
    ]
}

JSONがファクトリ内でハードコーディングされているときに、コントローラ、ファクトリ、およびhtmlが機能するようになりました。ただし、JSONを$ http.getコードに置き換えたため、機能しません。$ httpと$ resourceの両方のさまざまな例を見てきましたが、どこに行けばよいかわかりません。私は最も簡単な解決策を探しています。ng-repeatおよび同様のディレクティブのデータをプルしようとしています。

工場:

theApp.factory('mainInfoFactory', function($http) { 
    var mainInfo = $http.get('content.json').success(function(response) {
        return response.data;
    });
    var factory = {}; // define factory object
    factory.getMainInfo = function() { // define method on factory object
        return mainInfo; // returning data that was pulled in $http call
    };
    return factory; // returning factory to make it ready to be pulled by the controller
});

ありとあらゆる助けをいただければ幸いです。ありがとう!


1
動かない?それは何をするためのものか?エラーをスローしますか?JavaScriptコンソールに出力はありますか?
Josh Lee

コンソールには「リソースの読み込みに失敗しました」と表示され、console.jsonファイルパスが表示されます。そのため、何らかの理由でロードされていません。私のファクトリとJSONは、上記のとおりです。JSONをファクトリにハードコードすると、機能します。
jstacks 2013年

1
バックエンドとして何を使用していますか?NodeJまたは単純なPythonベースのサーバーまたは何か他のもの?
callmekatootie 2013年

バックエンド(Rails)を除いて開発しようとしています。したがって、JSONは上記のデータがハードコードされた単なる.jsonファイルです。おそらく、バックエンドがレンダリングするものと似ています。
jstacks 2013年

返されたJSONが「data」オブジェクト内にバンドルされていない限り、応答に「.data」は必要ない場合があります。「returnresponse;」に変更してください。
バースカラケンパイア2013年

回答:


218

さて、ここに調べるべきもののリストがあります:

1)いかなる種類のウェブサーバーも実行しておらず、file://index.htmlでテストしているだけの場合は、同一生成元ポリシーの問題が発生している可能性があります。見る:

https://code.google.com/archive/p/browsersec/wikis/Part2.wiki#Same-origin_policy

多くのブラウザでは、ローカルでホストされているファイルが他のローカルでホストされているファイルにアクセスすることを許可していません。Firefoxはそれを許可しますが、ロードするファイルがhtmlファイル(またはサブフォルダー)と同じフォルダーに含まれている場合に限ります。

2)$ http.get()から返された成功関数は、すでに結果オブジェクトを分割しています。

$http({method: 'GET', url: '/someUrl'}).success(function(data, status, headers, config) {

したがって、function(response)を使用してsuccessを呼び出し、response.dataを返すのは冗長です。

3)成功関数は、渡した関数の結果を返さないため、これはあなたが思っていることをしません。

var mainInfo = $http.get('content.json').success(function(response) {
        return response.data;
    });

これはあなたが意図したものに近いです:

var mainInfo = null;
$http.get('content.json').success(function(data) {
    mainInfo = data;
});

4)しかし、本当にやりたいのは、データのロード時に入力されるプロパティを持つオブジェクトへの参照を返すことです。したがって、次のようになります。

theApp.factory('mainInfo', function($http) { 

    var obj = {content:null};

    $http.get('content.json').success(function(data) {
        // you can do some processing here
        obj.content = data;
    });    

    return obj;    
});

mainInfo.contentはnullから始まり、データが読み込まれると、それを指します。

または、$ http.getが返す実際の約束を返し、それを使用することもできます。

theApp.factory('mainInfo', function($http) { 
    return $http.get('content.json');
});

そして、コントローラーの計算で値を非同期的に使用できます。

$scope.foo = "Hello World";
mainInfo.success(function(data) { 
    $scope.foo = "Hello "+data.contentItem[0].username;
});

27
ねえ、それは同じ価格での応答と角度のある$ httpコースです-いい答えです!
マット

4
4)の説明では、$ http.get()が解決される前に「returnobj」が呼び出されませんか?それが私に起こっていることだと思うので、ただ尋ねるだけです。
pathsofdesign 2014年

3
はい、そうなります。ただし、$ http.get()が解決されたときに呼び出されるクロージャーは、「obj」への参照を保持します。それはあなたがそれから使うことができるcontentプロパティを埋めます。
Karen Zilles 2014年

#4を使用するよりも#3の2番目の形式を使用することの問題は何ですか?
スペンサー

1
連鎖コールバック.success()は非推奨になりました。代わりに.then(success、error)を使用してください。
ティモシーペレス

21

受理された回答の4番目の部分が間違っていることに注意したかっ

theApp.factory('mainInfo', function($http) { 

var obj = {content:null};

$http.get('content.json').success(function(data) {
    // you can do some processing here
    obj.content = data;
});    

return obj;    
});

@Karl Zillesが書いた上記のコードobjは、データを受信する前に常に返されるため失敗します(したがって、値は常にになりますnull)。これは、非同期呼び出しを行っているためです。

同様の質問の詳細は、この投稿で説明されています


Angularでは$promise、非同期呼び出しを行うときに、フェッチされたデータを処理するために使用します。

最も単純なバージョンは

theApp.factory('mainInfo', function($http) { 
    return {
        get:  function(){
            $http.get('content.json'); // this will return a promise to controller
        }
});


// and in controller

mainInfo.get().then(function(response) { 
    $scope.foo = response.data.contentItem;
});

私が使用していない理由successerror、私はちょうどから発見されたドキュメントは、これらの2つの方法が推奨されていません。

$httpレガシー約束方法の成功とエラーが廃止されました。then代わりに標準の方法を使用してください。


2
return $http.get('content.json');工場で使用します。それ以外の場合、戻り値はnullです。
フランチェスコ

2
ねえ、ただ頭を上げて。それが機能する理由(ここでのあなたの答えとは反対に)は、オブジェクトへの参照を返すためです。成功関数には、同じオブジェクトへの参照もあります。ajax関数が最終的に戻ると、返された元のオブジェクトの「content」プロパティが更新されます。それを試してみてください。:-)
Karen Zilles 2015

1
Ps.successは非推奨になりました。.then代わりに使用してください。docs.angularjs.org/api/ng/service/$http
redfox05 2015

4

この答えは私を大いに助け、正しい方向に私を向けましたが、私、そしてうまくいけば他の人のために働いたのは:

menuApp.controller("dynamicMenuController", function($scope, $http) {
$scope.appetizers= [];
$http.get('config/menu.json').success(function(data) { 
    console.log("success!");
    $scope.appetizers = data.appetizers;
        console.log(data.appetizers);
    });    
});

6
サービス内でこのようなことをするべきではありませんか?
カタナ24 2014

コントローラでこれを行わないでください!悪い!これをサービスとして作成する必要があります。json値を呼び出す方法は間違っていませんが、コントローラーでこれを行わないという約束を返すサービスが必要です。再利用性の観点からも、これは恐ろしいことです。たとえば、コントローラーをロードするたびに$ http.get()を実行しているのに対し、サービスにキャッシュされたバージョンの呼び出しがあるとします。
downpour046 2016

1

私はおおよそこれらの問題を抱えています。Visual Studio2013からAngularJsアプリケーションをデバッグする必要があります。

デフォルトでは、IIS Expressはローカルファイル(jsonなど)へのアクセスを制限していました。

しかし、最初に:JSONにはJavaScript構文があります。

2番目:javascriptファイルが許可されます。

そう:

  1. JSONの名前をJS(data.json->data.js)に変更します。

  2. 正しいロードコマンド($http.get('App/data.js').success(function (data) {...

  3. スクリプトdata.jsをページにロードします(<script src="App/data.js"></script>

次に、ロードされたデータを通常の方法で使用します。もちろん、これは単なる回避策です。


1

++これは私のために働いた。これはvanilla javascirptngMocksライブラリでテストするときの整理などのユースケースに適しています。

<!-- specRunner.html - keep this at the top of your <script> asset loading so that it is available readily -->
<!--  Frienly tip - have all JSON files in a json-data folder for keeping things organized-->
<script src="json-data/findByIdResults.js" charset="utf-8"></script>
<script src="json-data/movieResults.js" charset="utf-8"></script>

これはデータjavascriptを含むファイルですJSON

// json-data/JSONFindByIdResults.js
var JSONFindByIdResults = {
     "Title": "Star Wars",
     "Year": "1983",
     "Rated": "N/A",
     "Released": "01 May 1983",
     "Runtime": "N/A",
     "Genre": "Action, Adventure, Sci-Fi",
     "Director": "N/A",
     "Writer": "N/A",
     "Actors": "Harrison Ford, Alec Guinness, Mark Hamill, James Earl Jones",
     "Plot": "N/A",
     "Language": "English",
     "Country": "USA",
     "Awards": "N/A",
     "Poster": "N/A",
     "Metascore": "N/A",
     "imdbRating": "7.9",
     "imdbVotes": "342",
     "imdbID": "tt0251413",
     "Type": "game",
     "Response": "True"
};

最後に、コード内の任意の場所でJSONデータを操作します

// working with JSON data in code
var findByIdResults = window.JSONFindByIdResults;

注:-これはテストに最適であり、karma.conf.js以下に示すように、テストを実行するためにこれらのファイルを受け入れます。また、これはデータとtesting/development環境を整理するためにのみお勧めします。

// extract from karma.conf.js
files: [
     'json-data/JSONSearchResultHardcodedData.js',
     'json-data/JSONFindByIdResults.js'
     ...
]

お役に立てれば。

++この回答の上に構築https://stackoverflow.com/a/24378510/4742733

更新

私のために働いたより簡単な方法functionは、コードの最後に何でも返すを含めることJSONです。

// within test code
let movies = getMovieSearchJSON();
.....
...
...
....
// way down below in the code
function getMovieSearchJSON() {
      return {
         "Title": "Bri Squared",
         "Year": "2011",
         "Rated": "N/A",
         "Released": "N/A",
         "Runtime": "N/A",
         "Genre": "Comedy",
         "Director": "Joy Gohring",
         "Writer": "Briana Lane",
         "Actors": "Brianne Davis, Briana Lane, Jorge Garcia, Gabriel Tigerman",
         "Plot": "N/A",
         "Language": "English",
         "Country": "USA",
         "Awards": "N/A",
         "Poster": "http://ia.media-imdb.com/images/M/MV5BMjEzNDUxMDI4OV5BMl5BanBnXkFtZTcwMjE2MzczNQ@@._V1_SX300.jpg",
         "Metascore": "N/A",
         "imdbRating": "8.2",
         "imdbVotes": "5",
         "imdbID": "tt1937109",
         "Type": "movie",
         "Response": "True"
   }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.