Chcę rozwijać się lokalnie, używając tylko zakodowanego na stałe pliku JSON. Mój plik JSON jest następujący (ważny po umieszczeniu w walidatorze 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" }
]
}
]
}
Mój kontroler, fabryka i html działały, gdy JSON został zakodowany na stałe w fabryce. Jednak teraz, gdy zastąpiłem JSON kodem $ http.get, nie działa. Widziałem wiele różnych przykładów zasobów $ http i $, ale nie jestem pewien, gdzie się udać. Szukam najprostszego rozwiązania. Po prostu próbuję pobrać dane dla instrukcji ng-repeat i podobnych.
Fabryka:
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
});
Wszelka pomoc jest mile widziana. Dzięki!
Odpowiedzi:
OK, oto lista spraw, którym należy się przyjrzeć:
1) Jeśli nie używasz żadnego serwera WWW i tylko testujesz z plikiem: //index.html, prawdopodobnie masz problemy z zasadami tego samego pochodzenia. Widzieć:
https://code.google.com/archive/p/browsersec/wikis/Part2.wiki#Same-origin_policy
Wiele przeglądarek nie zezwala plikom hostowanym lokalnie na dostęp do innych plików obsługiwanych lokalnie. Firefox na to zezwala, ale tylko wtedy, gdy ładowany plik znajduje się w tym samym folderze co plik HTML (lub podfolder).
2) Funkcja sukcesu zwrócona z $ http.get () już dzieli obiekt wynikowy za Ciebie:
$http({method: 'GET', url: '/someUrl'}).success(function(data, status, headers, config) {
Dlatego wywołanie sukcesu z funkcją (odpowiedzią) i zwrócenie odpowiedzi.data jest zbędne.
3) Funkcja sukcesu nie zwraca wyniku funkcji, którą ją przekazujesz, więc nie robi tego, co myślisz, że robi:
var mainInfo = $http.get('content.json').success(function(response) { return response.data; });
To jest bliżej tego, co zamierzałeś:
var mainInfo = null; $http.get('content.json').success(function(data) { mainInfo = data; });
4) Ale to, co naprawdę chcesz zrobić, to zwrócić odwołanie do obiektu z właściwością, która zostanie zapełniona po załadowaniu danych, więc coś takiego:
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 rozpocznie się od null, a po załadowaniu danych wskaże go.
Alternatywnie możesz zwrócić rzeczywistą obietnicę zwrotu $ http.get i użyć tego:
theApp.factory('mainInfo', function($http) { return $http.get('content.json'); });
Następnie możesz użyć tej wartości asynchronicznie w obliczeniach w kontrolerze:
$scope.foo = "Hello World"; mainInfo.success(function(data) { $scope.foo = "Hello "+data.contentItem[0].username; });
źródło
Chciałem zauważyć, że czwarta część zaakceptowanej odpowiedzi jest błędna .
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; });
Powyższy kod, który napisał @Karl Zilles zakończy się niepowodzeniem, ponieważ
obj
zawsze zostanie zwrócony przed otrzymaniem danych (w związku z tym wartość zawsze będzienull
), a to dlatego, że wykonujemy wywołanie asynchroniczne.Szczegóły podobnych pytań omówiono w tym poście
W Angular użyj
$promise
do obsługi pobranych danych, gdy chcesz wykonać wywołanie asynchroniczne.Najprostsza wersja to
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; });
Powodem, dla którego nie używam
success
ierror
właśnie dowiedziałem się z dokumentu , te dwie metody są przestarzałe.źródło
return $http.get('content.json');
w fabryce, w przeciwnym razie zwrot jest zerowy..success
jest teraz przestarzały. Użyj.then
zamiast tego. docs.angularjs.org/api/ng/service/$httpta odpowiedź bardzo mi pomogła i wskazała mi właściwy kierunek, ale to, co zadziałało dla mnie i, mam nadzieję, innych, to:
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); }); });
źródło
Mam w przybliżeniu ten problem. Potrzebuję debugowania aplikacji AngularJs z Visual Studio 2013.
Domyślnie IIS Express ograniczony dostęp do plików lokalnych (takich jak json).
Ale po pierwsze: JSON ma składnię JavaScript.
Po drugie: dozwolone są pliki javascript.
Więc:
zmień nazwę JSON na JS (
data.json->data.js
).prawidłowe polecenie ładowania (
$http.get('App/data.js').success(function (data) {...
ładowanie skryptu data.js do strony (
<script src="App/data.js"></script>
)Następnie użyj załadowanych danych w zwykły sposób. To oczywiście tylko obejście.
źródło
++ To zadziałało dla mnie. Jest to
vanilla javascirpt
dobre w przypadkach użycia, takich jak porządkowanie podczas testowania zngMocks
biblioteką:<!-- 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>
To jest twój
javascript
plik, który zawieraJSON
dane// 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" };
Na koniec pracuj z danymi JSON w dowolnym miejscu kodu
// working with JSON data in code var findByIdResults = window.JSONFindByIdResults;
Uwaga: - To jest świetne do testowania, a nawet
karma.conf.js
akceptuje te pliki do uruchamiania testów, jak pokazano poniżej. Polecam to tylko do porządkowania danych itesting/development
środowiska.// extract from karma.conf.js files: [ 'json-data/JSONSearchResultHardcodedData.js', 'json-data/JSONFindByIdResults.js' ... ]
Mam nadzieję że to pomoże.
++ Zbudowany na podstawie tej odpowiedzi https://stackoverflow.com/a/24378510/4742733
AKTUALIZACJA
Łatwiejszym sposobem, który zadziałał dla mnie, jest po prostu umieszczenie
function
na dole kodu zwracającego cokolwiekJSON
.// 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" } }
źródło