AngularJS:工厂$ http.get JSON文件


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正常工作。但是,现在我已经用$ http.get代码替换了JSON,它不起作用了。我已经看过$ 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控制台中是否有任何输出?
乔什·李

控制台仅显示“无法加载资源”,然后显示console.json文件路径。因此由于某种原因它没有加载它。我的工厂和JSON与您在上面看到的完全一样。当我将JSON硬编码到工厂时,它就可以工作。
jstacks

1
您使用什么作为后端?NodeJ还是基于python的简单服务器或其他工具?
callmekatootie

我只是在尝试排除后端(Rails)。因此,JSON只是一个.json文件,上面的数据经过了硬编码。大概类似于后端将呈现的内容。
jstacks

您可能不需要在响应中添加“ .data”。将其更改为“返回响应;”,除非您返回的JSON捆绑在“数据”对象中。
Bhaskara Kempaiah 2013年

Answers:


218

好的,这是需要调查的事情清单:

1)如果您没有运行任何类型的Web服务器,而只是使用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)调用成功并返回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()之前不会调用'return obj'吗?只是问一下,因为我认为那是发生在我身上的事情。
Pathsofdesign 2014年

3
是的,它会的。但是在解析$ http.get()时调用的闭包将保留对'obj'的引用。它将填充内容属性,然后可以使用它。
卡伦·兹莱斯

与#4相比,使用#3的第二种形式有什么问题?
斯宾塞

1
链接的回调.success()已被弃用。使用.then(成功,错误)代替。
蒂莫西·佩雷斯

21

我想指出,“接受的答案”第四部分是错误的

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是我刚刚从发现的文档,这两种方法已被弃用。

$http遗产的承诺方法成功和错误已被弃用。请改用标准then方法。


2
return $http.get('content.json');在工厂使用,否则return为null。
Francesco

2
嘿,只是抬起头。它起作用的原因(与您的回答相反)是您返回对对象的引用。成功函数还具有对同一对象的引用。当ajax函数最终返回时,它将更新返回的原始对象中的“ content”属性。尝试一下。:-)
Karen Zilles 2015年

1
.success现在不建议使用Ps 。使用.then代替。docs.angularjs.org/api/ng/service/$http
redfox05

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
您不应该在服务中执行类似的操作吗?
Katana24年

绝对不要在控制器中这样做!坏!您应该将此作为服务编写。尽管调用json值的方式没有错,但是您应该让Service返回在控制器中不执行此操作的诺言。从可重用性的角度来看,这也是可怕的。例如,每次加载控制器时都会执行$ http.get(),而不是在服务中包含调用的缓存版本。
Downpour046

1

我大概有这些问题。我需要从Visual Studio 2013调试AngularJs应用程序。

默认情况下,IIS Express限制了对本地文件(如json)的访问。

但是,首先:JSON具有JavaScript语法。

第二:允许使用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 javascirpt和良好的使用情况下,如与测试时去杂乱ngMocks库:

<!-- 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,在代码的底部包含一个返回any的代码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"
   }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.