AngularJS: fichier JSON $ http.get d'usine

84

Je cherche à développer localement avec juste un fichier JSON codé en dur. Mon fichier JSON est le suivant (valide lorsqu'il est placé dans le validateur 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" }
            ]
        }
    ]
}

J'ai fait fonctionner mon contrôleur, mon usine et mon code HTML lorsque le JSON a été codé en dur à l'intérieur de l'usine. Cependant, maintenant que j'ai remplacé le JSON par le code $ http.get, cela ne fonctionne pas. J'ai vu tellement d'exemples différents de $ http et $ resource mais je ne sais pas trop où aller. Je recherche la solution la plus simple. J'essaie juste d'extraire des données pour ng-repeat et des directives similaires.

Usine:

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

Toute aide est appréciée. Merci!

jstacks
la source
1
Ça ne marche pas? Qu'est ce que ça fait? Cela génère-t-il une erreur? Y a-t-il une sortie dans la console JavaScript?
Josh Lee
La console dit simplement «Échec du chargement de la ressource», puis a le chemin du fichier console.json. Donc, il ne le charge pas pour une raison quelconque. Mon usine et JSON sont exactement comme vous le voyez ci-dessus. Lorsque je code en dur le JSON dans l'usine, cela fonctionne.
jstacks
1
Qu'utilisez-vous comme backend? NodeJs ou un simple serveur basé sur Python ou autre chose?
callmekatootie
J'essaie juste de développer en excluant le backend (Rails). Donc, le JSON est juste un fichier .json avec les données ci-dessus codées en dur. Vraisemblablement similaire à ce que le backend rendrait.
jstacks
Vous n'aurez peut-être pas besoin de ".data" sur la réponse .. changez en - "return response;", à moins que votre JSON retourné ne soit intégré dans un objet 'data'.
Bhaskara Kempaiah

Réponses:

218

D'accord, voici une liste de choses à examiner:

1) Si vous n'exécutez pas de serveur Web de quelque type que ce soit et que vous testez simplement avec file: //index.html, vous rencontrez probablement des problèmes de politique de même origine. Voir:

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

De nombreux navigateurs n'autorisent pas les fichiers hébergés localement à accéder à d'autres fichiers hébergés localement. Firefox l'autorise, mais uniquement si le fichier que vous chargez est contenu dans le même dossier que le fichier html (ou un sous-dossier).

2) La fonction de succès renvoyée par $ http.get () divise déjà l'objet résultat pour vous:

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

Il est donc redondant d'appeler success avec function (response) et de renvoyer response.data.

3) La fonction de succès ne renvoie pas le résultat de la fonction que vous lui passez, donc cela ne fait pas ce que vous pensez qu'elle fait:

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

C'est plus proche de ce que vous vouliez:

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

4) Mais ce que vous voulez vraiment faire est de retourner une référence à un objet avec une propriété qui sera remplie lors du chargement des données, donc quelque chose comme ceci:

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 commencera par null, et lorsque les données se chargeront, il pointera dessus.

Vous pouvez également renvoyer la promesse réelle renvoyée par $ http.get et l'utiliser:

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

Et puis, vous pouvez utiliser la valeur de manière asynchrone dans les calculs dans un contrôleur:

$scope.foo = "Hello World";
mainInfo.success(function(data) { 
    $scope.foo = "Hello "+data.contentItem[0].username;
});
Karen Zilles
la source
27
Hé c'est une réponse ET un cours angulaire $ http pour le même prix - Belle réponse!
Mat
4
Dans votre explication sous 4), le 'return obj' ne sera-t-il pas appelé avant que $ http.get () ne soit résolu? Juste demander parce que je pense que c'est ce qui m'arrive.
Pathsofdesign
3
Oui, il sera. Mais la fermeture appelée quand $ http.get () est résolu garde une référence à 'obj'. Il remplira la propriété de contenu que vous pourrez ensuite utiliser.
Karen Zilles
Qu'est-ce qui pose problème avec l'utilisation de la deuxième forme de # 3 par rapport à # 4?
Spencer
1
Le rappel chaîné .success () est obsolète. Utilisez plutôt .then (succès, erreur).
Timothy Perez
21

Je voulais noter que la quatrième partie de la réponse acceptée est fausse .

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

Le code ci-dessus écrit par @Karl Zilles échouera car il objsera toujours retourné avant de recevoir des données (donc la valeur sera toujours null) et c'est parce que nous faisons un appel asynchrone.

Les détails de questions similaires sont discutés dans cet article


Dans Angular, utilisez $promisepour gérer les données extraites lorsque vous souhaitez effectuer un appel asynchrone.

La version la plus simple est

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

La raison pour laquelle je n'utilise pas successet errorc'est que je viens de le découvrir dans la documentation , ces deux méthodes sont obsolètes.

Le $httpsuccès et l'erreur des méthodes de promesse héritées sont obsolètes. Utilisez thenplutôt la méthode standard .

Qiang
la source
2
Utilisation return $http.get('content.json');en usine, sinon return est nul.
Francesco
2
Hé, juste un avertissement. La raison pour laquelle cela fonctionne (contrairement à votre réponse ici) est que vous renvoyez une référence à un objet. La fonction de succès a également une référence à ce même objet. Lorsque la fonction ajax finit par retourner, elle met à jour la propriété "content" dans l'objet d'origine qui a été renvoyé. Essayez-le. :-)
Karen Zilles
1
Ps .successest désormais obsolète. Utilisez .thenplutôt. docs.angularjs.org/api/ng/service/$http
redfox05
4

cette réponse m'a beaucoup aidé et m'a orienté dans la bonne direction, mais ce qui a fonctionné pour moi, et j'espère pour d'autres, c'est:

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);
    });    
});
jp093121
la source
6
ne devriez-vous pas faire quelque chose comme ça dans un service?
Katana24
Ne faites jamais cela dans un contrôleur! mal! Vous devriez l'avoir écrit en tant que service. Bien que la façon dont vous avez appelé la valeur json ne soit pas erronée, vous devriez avoir un service renvoyant la promesse de ne pas le faire dans le contrôleur. Du point de vue de la réutilisabilité, c'est aussi horrible. Par exemple, vous exécutez et $ http.get () chaque fois que vous chargez le contrôleur par rapport à une version mise en cache de l'appel dans un service.
Downpour046
1

J'ai à peu près ces problèmes. J'ai besoin de l'application de débogage AngularJs de Visual Studio 2013.

Par défaut, IIS Express restreint l'accès aux fichiers locaux (comme json).

Mais d'abord: JSON a une syntaxe JavaScript.

Deuxièmement: les fichiers javascript sont autorisés.

Donc:

  1. renommer JSON en JS ( data.json->data.js).

  2. commande de chargement correcte ($http.get('App/data.js').success(function (data) {...

  3. charger le script data.js sur la page ( <script src="App/data.js"></script>)

Ensuite, utilisez les données chargées de manière habituelle. C'est juste une solution de contournement, bien sûr.

Alex Sam
la source
1

++ Cela a fonctionné pour moi. C'est vanilla javascirptbon pour les cas d'utilisation tels que le désencombrement lors des tests avec la ngMocksbibliothèque:

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

C'est votre javascriptfichier qui contient les JSONdonnées

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

Enfin, travaillez avec les données JSON n'importe où dans votre code

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

Remarque: - Ceci est idéal pour les tests et karma.conf.jsaccepte même ces fichiers pour exécuter des tests comme indiqué ci-dessous. De plus, je recommande cela uniquement pour désencombrer les données et l' testing/developmentenvironnement.

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

J'espère que cela t'aides.

++ Construit sur cette réponse https://stackoverflow.com/a/24378510/4742733

MISE À JOUR

Un moyen plus simple qui a fonctionné pour moi est simplement d'inclure un functionen bas du code retournant quoi que ce soit 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"
   }
}
Aakash
la source