Javascript 在angular controller中访问HTTP GET JSON属性

Javascript 在angular controller中访问HTTP GET JSON属性,javascript,json,angularjs,Javascript,Json,Angularjs,我使用angular.js中的工厂和$http.get方法获取和处理JSON数据。JSON数据似乎已成功解析到工厂中,但我无法访问此JSON数据的属性 以下是我的js代码: var app = angular.module("app", []); app.factory('mainInfo', function($http) { var obj = {content:null}; //the php will return json data below

我使用angular.js中的工厂和$http.get方法获取和处理JSON数据。JSON数据似乎已成功解析到工厂中,但我无法访问此JSON数据的属性

以下是我的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;
}) ;
现在,如果我尝试在
Ctrl
controller中访问foo,网页将不显示任何数据:
控制器:{{foo}

但是,如果我在
Ctrl
中更改为
$scope.foo=mainfo
,则网页将正确显示JSON数据

我可以知道在
Ctrl
controller中访问
mainfo.content
属性的正确方法吗?

我需要访问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);
    };
});
关于工厂控制器通信,我只是引用另一篇文章中的解决方案:

试试这个:

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;
    });
}) ;
试试这个

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;
您以前的方法不起作用的原因是,您正在重新分配
obj
content
属性,从而破坏了以前的任何引用

这也是使用
$scope.foo=mainfo
有效的原因,因为对
obj
(通过
mainfo
)的引用被保留

在填充数据时,使用保持先前的参考


$http
承诺解析时(由于
$http
触发摘要循环),模板中的引用将得到更新。要访问控制器中的数据,请使用
$promise
属性

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


如果您与多个消费者(如控制器)共享工厂,则在工厂内维护数据是一个好主意。它们可能都引用了
mainfo.content
mainfo.$promise
,并且都将访问相同的数据集。

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

像这样使用$http(无需使用$q.defer(),如其他注释所示):


啊,一旦阿加尼同意在这种情况下,我应该把$http的承诺锁起来。。。我的错误。然而,我倾向于发现这种模式在许多情况下很有用,在这些情况下,我更喜欢对服务中的数据进行错误处理或处理,而不是使用服务的每个控制器。在我看来,它作为一种反模式的原因并不比它在这些情况下提供的干性能力更重要。@GPicazo这就是承诺链如此有效的原因。您可以在您的服务中处理错误、转换、进一步请求等,最后只需返回一个承诺。当您已经有一个延迟对象时,您不必使用延迟对象promise@GPicazo您可以返回链接内。然后处理数据/处理错误。例如,在您的帖子中,只需替换
deferred.resolve(response.records)带有
返回响应记录这实际上根本不是问题所在。OP试图在他们的工厂内维护数据。你会注意到,他们说如果使用
$scope.foo=mainfo
,它可以正常工作。问题是由于JavaScript引用$scope.foo=mainfo将范围对象设置为工厂返回的同一对象——执行此操作时,一旦设置了mainfo.content(或$scope.foo.content,相同引用),对象属性的更改将反映在模板中。但是,如果不链接到$http.get承诺,则这不会改变控制器在解析承诺之前设置值的情况。如果工厂返回原语值而不是对象,那么如果不使用promise,您将面临同样的问题如果您检查OP引用的post,它将提供相同的两个选项—返回其数据将稍后设置的对象(如OP中的对象),或者返回$http承诺本身。此外,问题特别是“访问控制器中此数据的正确方式是什么?”唯一的答案是使用一个承诺——让工厂返回一个对象,该对象的数据稍后将被设置,这对于模板化来说是很好的,但是要在控制器中对数据执行代码,您应该链接到$http.get promise。您关于链接到成功的说法是正确的,在这里不合适,尽管它是可链接的。它返回原始承诺而不是新承诺,因此“.then”chained将获得原始响应,而不是.success返回的值--我忽略了这一点,并进行了适当的编辑。请注意,工厂中的数据将一直存在,并且可以通过mainfo.getRecords访问,将来被其他模块访问时,这将是一个解决的承诺
$scope.foo = mainInfo.content;
mainInfo.$promise.then(function(data) {
    // access data.records here
});
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;
    });
}) ;