AngularJS: fabrika $ http.get JSON dosyası


84

Yalnızca kodlanmış bir JSON dosyasıyla yerel olarak geliştirmek istiyorum. JSON dosyam aşağıdaki gibidir (JSON doğrulayıcısına yerleştirildiğinde geçerlidir):

{
    "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 fabrika içinde kodlandığında denetleyicimi, fabrikamı ve html'imi çalıştırdım. Ancak, JSON'u $ http.get koduyla değiştirdiğime göre artık çalışmıyor. Hem $ http hem de $ resource için pek çok farklı örnek gördüm ama nereye gideceğimi bilmiyorum. En basit çözümü arıyorum. Sadece ng-tekrar ve benzer direktifler için veri almaya çalışıyorum.

Fabrika:

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

Her türlü yardım takdir edilmektedir. Teşekkürler!


1
Çalışmıyor mu? Bu ne işe yarıyor? Bir hata mı veriyor? JavaScript konsolunda herhangi bir çıktı var mı?
Josh Lee

Konsol yalnızca "Kaynak yüklenemedi" der ve ardından console.json dosya yolunu alır. Yani bir sebepten dolayı yüklenmiyor. Fabrikam ve JSON'm aynen yukarıda gördüğünüz gibi. JSON'u fabrikaya kodladığımda çalışıyor.
2013

1
Arka uç olarak ne kullanıyorsunuz? NodeJ'ler veya basit bir python tabanlı sunucu veya başka bir şey?
callmekatootie

Sadece arka ucu (Rails) hariç tutarak geliştirmeye çalışıyorum. Yani JSON, yukarıdaki verilerin kodlanmış olduğu bir .json dosyasıdır. Muhtemelen arka ucun oluşturacağına benzer.
jstacks

Yanıtta ".data" ya ihtiyacınız olmayabilir .. döndürdüğünüz JSON bir "veri" nesnesi içinde paketlenmediği sürece - "yanıtı döndür" olarak değiştirin.
Bhaskara Kempaiah 05

Yanıtlar:


218

Tamam, bakmanız gereken şeylerin bir listesi:

1) Herhangi bir türden bir web sunucusu çalıştırmıyorsanız ve sadece file: //index.html ile test yapıyorsanız, muhtemelen aynı kaynaklı politika sorunlarıyla karşılaşıyorsunuzdur. Görmek:

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

Çoğu tarayıcı, yerel olarak barındırılan dosyaların diğer yerel olarak barındırılan dosyalara erişmesine izin vermez. Firefox buna izin veriyor, ancak yalnızca yüklediğiniz dosya html dosyasıyla (veya bir alt klasörle) aynı klasörde bulunuyorsa.

2) $ http.get () işlevinden döndürülen başarı işlevi, sonuç nesnesini sizin için zaten böler:

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

Yani başarıyı function (response) ile çağırmak ve response.data döndürmek gereksizdir.

3) Başarı işlevi, geçirdiğiniz işlevin sonucunu döndürmez, dolayısıyla bu, sizin yaptığını düşündüğünüz şeyi yapmaz:

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

Bu, amaçladığınız şeye daha yakın:

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

4) Ama gerçekten yapmak istediğiniz şey, veri yüklendiğinde doldurulacak özelliğe sahip bir nesneye bir referans döndürmektir, bu nedenle şuna benzer bir şey:

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 ile başlayacak ve veri yüklendiğinde onu gösterecektir.

Alternatif olarak, $ http.get iadelerinin gerçek sözünü iade edebilir ve şunu kullanabilirsiniz:

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

Ve sonra değeri bir denetleyicideki hesaplamalarda eşzamansız olarak kullanabilirsiniz:

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

27
Hey bu bir yanıt VE aynı fiyata açısal bir $ http kursu - Güzel cevap!
Mat

4
4) altındaki açıklamanızda, $ http.get () çözülmeden önce 'return obj' çağrılmaz mı? Sadece soruyorum çünkü bence başıma gelen bu.
Pathsofdesign

3
Evet olacak. Ancak $ http.get () çözüldüğünde çağrılan kapanış 'obj' referansını tutar. Daha sonra kullanabileceğiniz içerik özelliğini dolduracaktır.
Karen Zilles

# 3'ün ikinci biçimini # 4 kullanmaya kıyasla sorunlu olan nedir?
Spencer

1
Zincirleme geri arama .success () kullanımdan kaldırıldı. Bunun yerine .then (başarı, hata) kullanın.
Timothy Perez

21

Kabul Edilen Yanıt'ın dördüncü bölümünün yanlış olduğunu belirtmek istedim .

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'in yazdığı gibi yukarıdaki kod başarısız objolacaktır , çünkü her zaman veri almadan önce döndürülecektir (bu nedenle değer her zaman olacaktır null) ve bunun nedeni Eşzamansız çağrı yapıyor olmamızdır .

Benzer soruların detayları bu yazıda tartışılıyor


Angular'da, $promiseeşzamansız bir arama yapmak istediğinizde getirilen verilerle ilgilenmek için kullanın .

En basit versiyon

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

Ben kullanmıyorum nedeni successve errorben sadece öğrendim olduğu doc , bu iki yöntemin kaldırılmıştır.

$httpEski vaadi yöntemleri başarı ve hata kullanımdan kaldırıldı. thenBunun yerine standart yöntemi kullanın.


2
return $http.get('content.json');Fabrikada kullanın , aksi takdirde iade geçersizdir.
Francesco

2
Hey, sadece bir uyarı. İşe yaramasının nedeni (buradaki cevabınızın tersine), bir nesneye referans veriyor olmanızdır. Başarı işlevinin de aynı nesneye bir referansı vardır. Ajax işlevi sonunda geri döndüğünde, döndürülen orijinal nesnedeki "content" özelliğini günceller. Dene. :-)
Karen Zilles

1
Ps .successartık kullanımdan kaldırılmıştır. .thenBunun yerine kullanın . docs.angularjs.org/api/ng/service/$http
redfox05

4

bu cevap bana çok yardımcı oldu ve beni doğru yöne yönlendirdi ama benim ve umarım diğerleri için işe yarayan şey şudur:

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
bir hizmetin içinde böyle bir şey yapmanız gerekmiyor mu?
Katana24

Bunu asla bir kontrolörde yapmayın! kötü! Bunu bir servis olarak yazmalısın. Json değerini çağırma şekliniz yanlış olmasa da, denetleyicide bunu yapmama vaadini veren bir Hizmete sahip olmalısınız. Yeniden kullanılabilirlik açısından da bu korkunç. Örneğin, denetleyiciyi her yüklediğinizde ve bir hizmette aramanın önbelleğe alınmış bir sürümüne sahip olduğunuzda $ http.get () gerçekleştiriyorsunuz.
Downpour046

1

Yaklaşık olarak bu problemim var. Visual Studio 2013'ten AngularJs uygulamasında hata ayıklamaya ihtiyacım var.

Varsayılan olarak IIS Express, yerel dosyalara (json gibi) erişimi kısıtlamıştır.

Ama önce: JSON'da JavaScript sözdizimi var.

İkincisi: javascript dosyalarına izin verilir.

Yani:

  1. JSON'u JS ( data.json->data.js) olarak yeniden adlandırın .

  2. doğru yükleme komutu ($http.get('App/data.js').success(function (data) {...

  3. kod dosyası data.js dosyasını sayfaya ( <script src="App/data.js"></script>) yükleyin

Daha sonra yüklenen verileri normal bir şekilde kullanın. Elbette bu sadece geçici bir çözüm.


1

++ Bu benim için çalıştı. Bu var vanilla javascirptve bu tür ile test de-yığılan gibi durumlar için iyi ngMockskütüphanede:

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

Bu, verileri javascriptiçeren dosyanızdırJSON

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

Son olarak, kodunuzun herhangi bir yerinde JSON verileriyle çalışın

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

Not: - Bu, test için harikadır ve hatta karma.conf.jsaşağıda görüldüğü gibi testleri çalıştırmak için bu dosyaları kabul eder. Ayrıca, bunu yalnızca verileri ve testing/developmentortamı dağıtmak için tavsiye ederim .

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

Bu yardımcı olur umarım.

++ Bu cevabın üzerine inşa edilmiştir https://stackoverflow.com/a/24378510/4742733

GÜNCELLEME

Benim için işe yarayan daha kolay bir yol function, kodun altına ne olursa olsun döndüren bir eklemektir 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"
   }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.