AngularJS:工厂 $http.get JSON 文件
Posted
技术标签:
【中文标题】AngularJS:工厂 $http.get JSON 文件【英文标题】:AngularJS: factory $http.get JSON file 【发布时间】:2013-05-31 14:17:00 【问题描述】:我希望仅使用硬编码的 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
);
感谢任何和所有帮助。谢谢!
【问题讨论】:
不行吗?它有什么作用?它会抛出错误吗? javascript 控制台中是否有任何输出? 控制台只是说“加载资源失败”,然后有 console.json 文件路径。所以由于某种原因它没有加载它。我的工厂和 JSON 与您在上面看到的完全一样。当我将 JSON 硬编码到工厂中时,它就可以工作了。 您使用什么作为后端? NodeJs 还是一个简单的基于 python 的服务器或其他东西? 我只是想开发不包括后端(Rails)。所以 JSON 只是一个 .json 文件,上面的数据是硬编码的。大概类似于后端将呈现的内容。 您可能不需要响应中的“.data”.. 更改为 --“return response;”,除非您返回的 JSON 捆绑在“data”对象中。 【参考方案1】:好的,以下是要调查的事项列表:
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;
);
【讨论】:
嘿,这是一个响应和一个角度相同的 $http 课程 - 很好的答案! 在 4) 下的解释中,在 $http.get() 解决之前不会调用“返回 obj”吗?只是问,因为我认为这就是发生在我身上的事情。 会的。但是当 $http.get() 被解析时调用的闭包保留了对 'obj' 的引用。它将填写您可以使用的内容属性。 使用#3 的第二种形式比使用#4 有什么问题? 链式回调 .success() 已被弃用。请改用 .then(success, error)。【参考方案2】:++ 这对我有用。它是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://***.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"
【讨论】:
【参考方案3】:我想指出 Accepted Answer 的第四部分是错误的 .
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
),这是因为我们正在进行异步调用。
类似问题详情在this post讨论
在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;
);
我不使用success
和error
的原因是我刚刚从doc中发现的,这两种方法已被弃用。
$http
旧式 promise 方法成功和错误已被弃用。请改用标准的then
方法。
【讨论】:
在工厂使用return $http.get('content.json');
,否则返回null。
嘿,请注意。它起作用的原因(与您在此处的回答相反)是您正在返回对对象的引用。成功函数也引用了同一个对象。当 ajax 函数最终返回时,它会更新返回的原始对象中的“内容”属性。试试吧。 :-)
附言。 .success
现在已弃用。请改用.then
。 docs.angularjs.org/api/ng/service/$http【参考方案4】:
我有大约这些问题。我需要从 Visual Studio 2013 调试 AngularJs 应用程序。
默认情况下,IIS Express 限制对本地文件(如 json)的访问。
但是,首先:JSON 具有 JavaScript 语法。
第二:允许使用javascript文件。
所以:
将 JSON 重命名为 JS (data.json->data.js
)。
正确的加载命令($http.get('App/data.js').success(function (data) ...
将脚本 data.js 加载到页面 (<script src="App/data.js"></script>
)
接下来以通常的方式使用加载的数据。当然,这只是一种解决方法。
【讨论】:
【参考方案5】:这个答案对我有很大帮助,并为我指明了正确的方向,但对我和希望其他人有用的是:
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);
);
);
【讨论】:
你不应该在服务中做这样的事情吗? 永远不要在控制器中这样做!坏的!你应该把它写成服务。尽管您调用 json 值的方式没有错,但您应该有一个服务返回承诺,而不是在控制器中执行此操作。从可重用性的角度来看,这也是可怕的。例如,您每次加载控制器时都在执行 $http.get() ,而不是在服务中使用缓存版本的调用。以上是关于AngularJS:工厂 $http.get JSON 文件的主要内容,如果未能解决你的问题,请参考以下文章
如何从AngularJS获得响应$ http.get()。then()
如何在 AngularJS 中正确使用 HTTP.GET?具体来说,对于外部 API 调用?
TypeScript/angularJS HTTP GET 请求中的范围