AngularJS: factory $ http.get tệp JSON


84

Tôi đang tìm cách phát triển cục bộ chỉ với một tệp JSON được mã hóa cứng. Tệp JSON của tôi như sau (hợp lệ khi được đưa vào trình xác thực 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" }
            ]
        }
    ]
}

Tôi đã làm cho bộ điều khiển, nhà máy và html của mình hoạt động khi JSON được mã hóa cứng bên trong nhà máy. Tuy nhiên, bây giờ tôi đã thay thế JSON bằng mã $ http.get, nó không hoạt động. Tôi đã thấy rất nhiều ví dụ khác nhau về cả tài nguyên $ http và $ nhưng không chắc nên đi đâu. Tôi đang tìm giải pháp đơn giản nhất. Tôi chỉ đang cố gắng lấy dữ liệu cho các lệnh ng-repeat và các lệnh tương tự.

Nhà máy:

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

Bất kỳ và tất cả các trợ giúp được đánh giá cao. Cảm ơn!


1
Nó không hoạt động? Nó làm gì? Nó có báo lỗi không? Có bất kỳ đầu ra nào trong bảng điều khiển JavaScript không?
Josh Lee

Bảng điều khiển chỉ thông báo "Không tải được tài nguyên" và sau đó có đường dẫn tệp console.json. Vì vậy, nó không tải nó vì một số lý do. Nhà máy của tôi và JSON chính xác như bạn thấy ở trên. Khi tôi hardcode JSON vào nhà máy, nó hoạt động.
jstacks

1
Bạn đang sử dụng gì làm chương trình phụ trợ của mình? NodeJs hoặc một máy chủ dựa trên python đơn giản hay thứ gì khác?
callmekatootie

Tôi chỉ đang cố gắng phát triển loại trừ phần phụ trợ (Rails). Vì vậy, JSON chỉ là một tệp .json với dữ liệu được mã hóa cứng ở trên. Có lẽ tương tự như những gì chương trình phụ trợ sẽ hiển thị.
jstacks

Bạn có thể không cần ".data" trên phản hồi .. thay đổi thành - "trả về phản hồi;", trừ khi JSON trả về của bạn được đóng gói bên trong đối tượng 'dữ liệu'.
Bhaskara Kempaiah

Câu trả lời:


218

Được rồi, đây là danh sách những điều cần xem xét:

1) Nếu bạn không chạy bất kỳ loại máy chủ web nào và chỉ thử nghiệm với tệp: //index.html, thì có thể bạn đang gặp phải các vấn đề về chính sách cùng nguồn gốc. Xem:

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

Nhiều trình duyệt không cho phép các tệp được lưu trữ cục bộ truy cập vào các tệp được lưu trữ cục bộ khác. Firefox cho phép nó, nhưng chỉ khi tệp bạn đang tải được chứa trong cùng một thư mục với tệp html (hoặc một thư mục con).

2) Hàm thành công được trả về từ $ http.get () đã chia nhỏ đối tượng kết quả cho bạn:

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

Vì vậy, việc gọi thành công với function (response) và trả về response.data là dư thừa.

3) Hàm thành công không trả về kết quả của hàm mà bạn truyền nó, vì vậy hàm này không thực hiện những gì bạn nghĩ:

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

Điều này gần với những gì bạn dự định:

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

4) Nhưng những gì bạn thực sự muốn làm là trả về một tham chiếu đến một đối tượng có thuộc tính sẽ được điền khi dữ liệu tải, vì vậy những thứ như sau:

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 sẽ bắt đầu bằng null và khi tải dữ liệu, nó sẽ trỏ vào nó.

Ngoài ra, bạn có thể trả lại lời hứa thực sự mà $ http.get trả về và sử dụng:

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

Và sau đó, bạn có thể sử dụng giá trị không đồng bộ trong các phép tính trong bộ điều khiển:

$scope.foo = "Hello World";
mainInfo.success(function(data) { 
    $scope.foo = "Hello "+data.contentItem[0].username;
});

27
Này, đó là câu trả lời VÀ một khóa học $ http góc cạnh với cùng một mức giá - Câu trả lời tốt!
Mat

4
Theo giải thích của bạn ở phần 4), sẽ không gọi 'return obj' trước khi $ http.get () được giải quyết? Chỉ hỏi vì tôi nghĩ đó là những gì đang xảy ra với tôi.
Pathsofdesign

3
Nó sẽ được thôi. Nhưng quá trình đóng được gọi khi $ http.get () được giải quyết vẫn giữ một tham chiếu đến 'obj'. Nó sẽ điền vào thuộc tính nội dung mà bạn có thể sử dụng.
Karen Zilles

Có vấn đề gì với việc sử dụng hình thức thứ hai của # 3 thay vì sử dụng # 4?
Spencer

1
Lệnh gọi lại chuỗi .success () không được dùng nữa. Sử dụng .then (thành công, lỗi) thay thế.
Timothy Perez

21

Tôi muốn lưu ý rằng phần thứ tư của Câu trả lời được chấp nhận là sai .

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

Đoạn mã trên với tên @Karl Zilles đã viết sẽ không thành công vì objsẽ luôn được trả về trước khi nó nhận dữ liệu (do đó giá trị sẽ luôn là null) và điều này là do chúng ta đang thực hiện lệnh gọi Không đồng bộ.

Chi tiết của các câu hỏi tương tự được thảo luận trong bài đăng này


Trong Angular, sử dụng $promiseđể xử lý dữ liệu đã tìm nạp khi bạn muốn thực hiện cuộc gọi không đồng bộ.

Phiên bản đơn giản nhất là

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

Lý do tôi không sử dụng successerrortôi mới tìm ra từ tài liệu , hai phương pháp này không được dùng nữa.

Các $http phương pháp thành công và lỗi kế thừa đã không được dùng nữa. Sử dụng thenphương pháp tiêu chuẩn để thay thế.


2
Sử dụng return $http.get('content.json');trong nhà máy, nếu không trả về là null.
Francesco

2
Này, vui lên. Lý do nó hoạt động (trái với câu trả lời của bạn ở đây) là bạn đang trả về một tham chiếu đến một đối tượng. Hàm thành công cũng có một tham chiếu đến cùng một đối tượng. Khi cuối cùng hàm ajax trả về, nó sẽ cập nhật thuộc tính "nội dung" trong đối tượng ban đầu được trả về. Thử nó. :-)
Karen Zilles

1
Ps .successhiện không được dùng nữa. Sử dụng .thenthay thế. docs.angularjs.org/api/ng/service/$http
redfox05

4

câu trả lời này đã giúp tôi rất nhiều và chỉ cho tôi đi đúng hướng nhưng điều hiệu quả với tôi và hy vọng những người khác là:

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
bạn không nên làm điều gì đó như thế này bên trong một dịch vụ?
Katana24

Không bao giờ làm điều này trong một bộ điều khiển! xấu! Bạn nên viết điều này như một dịch vụ. Mặc dù cách bạn gọi giá trị json không sai, nhưng bạn nên có một Dịch vụ trả về lời hứa không thực hiện điều này trong bộ điều khiển. Từ quan điểm khả năng tái sử dụng, điều này thật kinh khủng. Ví dụ: bạn đang thực hiện và $ http.get () mỗi khi bạn tải bộ điều khiển so với có phiên bản cuộc gọi được lưu trong bộ nhớ cache trong một dịch vụ.
Downpour046,

1

Tôi có khoảng những vấn đề này. Tôi cần gỡ lỗi ứng dụng AngularJs từ Visual Studio 2013.

Theo mặc định, IIS Express hạn chế quyền truy cập vào các tệp cục bộ (như json).

Nhưng, đầu tiên: JSON có cú pháp JavaScript.

Thứ hai: cho phép các tệp javascript.

Vì thế:

  1. đổi tên JSON thành JS ( data.json->data.js).

  2. lệnh tải đúng ($http.get('App/data.js').success(function (data) {...

  3. tải script data.js vào trang ( <script src="App/data.js"></script>)

Tiếp theo sử dụng dữ liệu đã tải theo cách thông thường. Tất nhiên, đó chỉ là cách giải quyết.


1

++ Điều này đã làm việc cho tôi. Nó vanilla javascirptvà tốt cho các trường hợp sử dụng chẳng hạn như loại bỏ lộn xộn khi kiểm tra với ngMocksthư viện:

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

Đây là javascripttệp của bạn chứa JSONdữ liệu

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

Cuối cùng, làm việc với dữ liệu JSON ở bất kỳ đâu trong mã của bạn

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

Lưu ý: - Điều này rất tốt để thử nghiệm và thậm chí karma.conf.jschấp nhận các tệp này để chạy thử nghiệm như được thấy bên dưới. Ngoài ra, tôi khuyến nghị điều này chỉ cho dữ liệu và testing/developmentmôi trường loại bỏ lộn xộn .

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

Hi vọng điêu nay co ich.

++ Được xây dựng dựa trên câu trả lời này https://stackoverflow.com/a/24378510/4742733

CẬP NHẬT

Một cách dễ dàng hơn phù hợp với tôi là chỉ cần bao gồm một functionở cuối mã trả về bất cứ điều gì 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"
   }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.