【问题标题】:AngularJS: factory $http.get JSON fileAngularJS:工厂 $http.get JSON 文件
【发布时间】: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”对象中。

标签: json http angularjs factory


【解决方案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://stackoverflow.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;
    });
    

    我不使用successerror的原因是我刚刚从doc中发现的,这两种方法已被弃用。

    $http 旧式 promise 方法成功和错误已被弃用。请改用标准的then 方法。

    【讨论】:

    • 在工厂使用return $http.get('content.json');,否则返回null。
    • 嘿,请注意。它起作用的原因(与您在此处的回答相反)是您正在返回对对象的引用。成功函数也引用了同一个对象。当 ajax 函数最终返回时,它会更新返回的原始对象中的“内容”属性。试试吧。 :-)
    • 附言。 .success 现在已弃用。请改用.thendocs.angularjs.org/api/ng/service/$http
    【解决方案4】:

    我有大约这些问题。我需要从 Visual Studio 2013 调试 AngularJs 应用程序。

    默认情况下,IIS Express 限制对本地文件(如 json)的访问。

    但是,首先:JSON 具有 JavaScript 语法。

    第二:允许使用javascript文件。

    所以:

    1. 将 JSON 重命名为 JS (data.json-&gt;data.js)。

    2. 正确的加载命令($http.get('App/data.js').success(function (data) {...

    3. 将脚本 data.js 加载到页面 (&lt;script src="App/data.js"&gt;&lt;/script&gt;)

    接下来以通常的方式使用加载的数据。当然,这只是一种解决方法。

    【讨论】:

      【解决方案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() ,而不是在服务中使用缓存版本的调用。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-05-02
      • 2015-05-23
      • 1970-01-01
      • 2023-04-08
      • 1970-01-01
      • 2014-05-03
      • 1970-01-01
      相关资源
      最近更新 更多