在角控制器中访问HTTP GET JSON属性

时间:2021-01-17 16:01:41

I am using a factory in angular.js and $http.get method to grab and process JSON data. The JSON data seems successfully parsed into factory, but I have problem access property of this JSON data.

我用的是有角的工厂。js和http。获取获取和处理JSON数据的方法。JSON数据似乎成功地解析为工厂,但我有这个JSON数据的问题访问属性。

Here is my js code:

以下是我的js代码:

var app = angular.module("app", []);      

app.factory('mainInfo', function($http) { 

    var obj = {content:null};
    //the php will return json data below
    $http.get('http://localhost/test.php').success(function(response){ 
        obj.content = response.records;

    });    

    return obj;    
});


app.controller('Ctrl', function($scope, mainInfo){
    $scope.foo = mainInfo.content;
}) ;

Now if I try to access foo within Ctrl controller, the webpage will display no data:
<div ng-controller="Ctrl">Controller: {{foo}}</div>
However, if I change to $scope.foo = mainInfo in the Ctrl, then the webpage will display correctly the JSON data.

现在,如果我尝试在Ctrl controller中访问foo,页面将不会显示任何数据:

controller: {{{{foo}}}}}}}< div>,如果我更改为$scope。在Ctrl中输入foo = mainInfo,页面将正确显示JSON数据。

May I know what is the proper way to access mainInfo.content property in Ctrl controller?

我想知道访问mainInfo的正确方法是什么。内容属性在Ctrl控制器中?

The reason why I need to access JSON property is because I need to pre-process the data. I intend to use these data in a Chart, as in below controller. Currently this controller is not working either, because I have the same problem accessing JSON property as in the Ctrl controller.

我需要访问JSON属性的原因是我需要对数据进行预处理。我打算在图表中使用这些数据,如下所示。目前这个控制器也不工作,因为我在访问JSON属性时遇到了与Ctrl控制器相同的问题。

app.controller("LineCtrl", function ($scope, mainInfo) {
    var timePoints = [];
    var percentagePoints = [];
    var i = 0;
    for( i = 0; i < mainInfo.content.length; i ++) {
        timePoints.push(mainInfo.content[i].Time);
        percentagePoints.push(mainInfo.content[i].Percentage);
    }

    $scope.labels = timePoints;

    $scope.data = percentagePoints;

    $scope.onClick = function (points, evt) {
        console.log(points, evt);
    };
});

The json data:

json数据:

{
"records": [
    {
        "Id": "1",
        "Time": "2015-07-25 08:00:00",
        "Percentage": "60"
    },
    {
        "Id": "2",
        "Time": "2015-07-25 09:00:00",
        "Percentage": "70"
    },
    {
        "Id": "3",
        "Time": "2015-07-25 10:00:00",
        "Percentage": "80"
    }
    ]
}

With regards to the factory-controller communication, I am just referring the solution from another post: reference

关于工厂-控制器通信,我只是引用了另一篇文章中的解决方案:reference

3 个解决方案

#1


7  

$http.get returns a promise -- your problem is that you are returning "obj" immediately, and your controller tries to access the data before the $http.get promise is resolved.

美元http。get返回一个承诺——您的问题是您正在立即返回“obj”,并且您的控制器试图在$http之前访问数据。承诺是解决。

use $http like so (no need to use $q.defer() as shown in the other comment):

使用$http like so(不需要使用$q. delay(),如其他注释所示):

var app = angular.module("app", []);      

app.factory('mainInfo', function($http) { 
    var getRecordsPromise = $http.get('http://localhost/test.php').then(function(response){ 
        //whatever is returned here will be accessible in the .then that is chained
        return response.data.records;
    });    

    return {
        getRecords: getRecordsPromise
    };    
});


app.controller('Ctrl', function($scope, mainInfo){
    mainInfo.getRecords.then(function (records) {
        $scope.foo = records;
    });
}) ;

#2


2  

Try this instead

试试这个相反

var obj = {content: []};
obj.$promise = $http.get('http://localhost/test.php').then(function(response) {
    angular.copy(response.data.records, obj.content);
    return response.data;
});
return obj;

The reason your former method didn't work was because you were re-assigning the content property of obj, thus destroying any previous references.

您以前的方法不起作用的原因是您重新分配了obj的内容属性,从而破坏了以前的引用。

This is also why using $scope.foo = mainInfo worked because the reference to obj (via mainInfo) was maintained.

这也是为什么要使用$scope。foo = mainInfo工作,因为对obj(通过mainInfo)的引用被维护。

Using angular.copy maintains the previous reference whilst populating the data.

使用角。复制在填充数据时维护先前的引用。


That should take care of references in the template that get updated when the $http promise resolves (due to $http triggering a digest cycle). For accessing the data in your controller, use the $promise property

当$http承诺解决时(由于$http触发摘要周期),模板中的引用将被更新,这应该会得到注意。要访问控制器中的数据,请使用$promise属性

$scope.foo = mainInfo.content;
mainInfo.$promise.then(function(data) {
    // access data.records here
});

Maintaining the data inside your factory is a good idea if you share your factory with multiple consumers (eg controllers). They may all reference mainInfo.content and mainInfo.$promise and all will be accessing the same data set.

如果您将工厂与多个使用者(如控制器)共享,那么在工厂内部维护数据是一个好主意。他们都可以参考主信息。内容和mainInfo。$promise和all将访问相同的数据集。

#3


0  

Try this:

试试这个:

var app = angular.module("app", []);      

app.factory('mainInfo', function($http) { 
    return {
        getData: function() {
            var deferred = $q.defer();


            //the php will return json data below
            $http.get('http://localhost/test.php').success(function(response){ 
                deferred.resolve(response.records);});



            return deferred.promise;
        }
    }
});


app.controller('Ctrl', function($scope, mainInfo){
    mainInfo.getData().then(function(result) {
        $scope.foo = result.content;
    });
}) ;

#1


7  

$http.get returns a promise -- your problem is that you are returning "obj" immediately, and your controller tries to access the data before the $http.get promise is resolved.

美元http。get返回一个承诺——您的问题是您正在立即返回“obj”,并且您的控制器试图在$http之前访问数据。承诺是解决。

use $http like so (no need to use $q.defer() as shown in the other comment):

使用$http like so(不需要使用$q. delay(),如其他注释所示):

var app = angular.module("app", []);      

app.factory('mainInfo', function($http) { 
    var getRecordsPromise = $http.get('http://localhost/test.php').then(function(response){ 
        //whatever is returned here will be accessible in the .then that is chained
        return response.data.records;
    });    

    return {
        getRecords: getRecordsPromise
    };    
});


app.controller('Ctrl', function($scope, mainInfo){
    mainInfo.getRecords.then(function (records) {
        $scope.foo = records;
    });
}) ;

#2


2  

Try this instead

试试这个相反

var obj = {content: []};
obj.$promise = $http.get('http://localhost/test.php').then(function(response) {
    angular.copy(response.data.records, obj.content);
    return response.data;
});
return obj;

The reason your former method didn't work was because you were re-assigning the content property of obj, thus destroying any previous references.

您以前的方法不起作用的原因是您重新分配了obj的内容属性,从而破坏了以前的引用。

This is also why using $scope.foo = mainInfo worked because the reference to obj (via mainInfo) was maintained.

这也是为什么要使用$scope。foo = mainInfo工作,因为对obj(通过mainInfo)的引用被维护。

Using angular.copy maintains the previous reference whilst populating the data.

使用角。复制在填充数据时维护先前的引用。


That should take care of references in the template that get updated when the $http promise resolves (due to $http triggering a digest cycle). For accessing the data in your controller, use the $promise property

当$http承诺解决时(由于$http触发摘要周期),模板中的引用将被更新,这应该会得到注意。要访问控制器中的数据,请使用$promise属性

$scope.foo = mainInfo.content;
mainInfo.$promise.then(function(data) {
    // access data.records here
});

Maintaining the data inside your factory is a good idea if you share your factory with multiple consumers (eg controllers). They may all reference mainInfo.content and mainInfo.$promise and all will be accessing the same data set.

如果您将工厂与多个使用者(如控制器)共享,那么在工厂内部维护数据是一个好主意。他们都可以参考主信息。内容和mainInfo。$promise和all将访问相同的数据集。

#3


0  

Try this:

试试这个:

var app = angular.module("app", []);      

app.factory('mainInfo', function($http) { 
    return {
        getData: function() {
            var deferred = $q.defer();


            //the php will return json data below
            $http.get('http://localhost/test.php').success(function(response){ 
                deferred.resolve(response.records);});



            return deferred.promise;
        }
    }
});


app.controller('Ctrl', function($scope, mainInfo){
    mainInfo.getData().then(function(result) {
        $scope.foo = result.content;
    });
}) ;