AngularJS: Factory $http.get JSON file

我希望只使用硬编码的 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
});

感谢你们的帮助,谢谢!

350163 次浏览

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

1)如果你不运行任何类型的网络服务器,只是测试文件://index.html,那么你可能会遇到同源策略问题。参见:

Https://code.google.com/archive/p/browsersec/wikis/part2.wiki#same-origin_policy

许多浏览器不允许本地托管文件访问其他本地托管文件。Firefox 确实允许这样做,但是只有当你加载的文件和 html 文件(或者子文件夹)包含在同一个文件夹中时才允许。

2)从 $http.get ()返回的 Success 函数已经为您分解了 result 对象:

$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;
});

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;
});

这个答案帮了我很大的忙,为我指明了正确的方向,但对我有用的是,希望对其他人也有用:

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);
});
});

我有大约这些问题。我需要从 VisualStudio2013调试 AngularJs 应用程序。

默认情况下,IISExpress 限制对本地文件(如 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>)

接下来用一种常见的方式来使用加载的数据。当然,这只是一种变通方法。

我想指出的是,接受答案的 < strong > 第四部分是错误的 .

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方法。

这招对我很管用。它是 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>

这是包含 JSON数据的 javascript文件

// 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

更新

对我来说,一个更简单的方法就是在代码底部包含一个返回任何 JSONfunction

// 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"
}
}