获取从 angularJS 中的异步 $http 服务获得的对象,以便在 $scope 中全局访问
Posted
技术标签:
【中文标题】获取从 angularJS 中的异步 $http 服务获得的对象,以便在 $scope 中全局访问【英文标题】:Getting the object obtained from asynchronous $http service in angularJS to be accessible globally in $scope 【发布时间】:2015-07-27 03:24:23 【问题描述】:我正在使用 Angular JS。我试图让使用 $http 服务获得的 json 对象可以在 $scope 变量中访问。在所有异步 AJAX ($http.get()) 调用中,如果我尝试打印存储在 $scope 变量中的数据并打印它,它会成功运行并向我显示预期的数据。但是在异步方法的范围之外,分配了数据的同一个 $scope 变量失去了对它的控制并打印出 undefined。
代码:
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q)
return
list: function()
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config)
deferred.resolve(data);
)
.error(function(data, status, headers, config)
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
);
return deferred.promise;
;
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$http', 'getTestcaseFactory', function($scope, $routeParams, $http, getTestcaseFactory)
$scope.myjsonobj = '';
var fetchTestcaseDetails = function()
getTestcaseFactory.list()
.then(
function(data)
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
,
function(data)
alert(data);
);
fetchTestcaseDetails();
console.log($scope.model); //Prints undefined
]);
【问题讨论】:
【参考方案1】:到时候
console.log($scope.model);
执行,$http
请求尚未通过,这就是它打印未定义的原因。一旦$http
请求完成,您的$scope.model
将相应更新。您可以使用$timeout
进行测试
$timeout(function ()
console.log($scope.model);
, 5000);
别忘了在你的控制器中注入$timeout
。
【讨论】:
虽然这个答案正确地指出了问题的本质,但 5000 超时是完全任意的,并且仅在某些时候有效,具体取决于实际调用需要多长时间。在回调中打印它,或者使用角度 $watch 机制使代码更面向数据,更少依赖时间。 感谢@Dan Moldovan!我也想通了可能是我必须使用计时器来等待 $http 服务完成并获得数据。 $timeout 完成这项工作。再次感谢! 很高兴帮助我的朋友! @doldt 你可以在这里分享一个 plunker 来展示你使用 $watch 解决这个问题的方法吗?在某处我看到了 $watch 方法,但我没有实施它来解决我的问题。 @SatyajitPatnaik 看到我的答案。【参考方案2】:这可以节省我的时间! $timeout 进行救援。感谢@Dan Moldovan 的回答!由于 $http 服务是异步的,我们必须设置一个计时器来等待一个时间间隔,直到在 promise.success 部分中真正接收到数据,然后才能将其分配给 $scope 内的变量。
var app = angular.module('chariot', ['ngRoute', 'ngFileUpload']);
app.factory('getTestcaseFactory', ['$http', '$routeParams', '$q', function($http, $routeParams, $q)
return
list: function()
var deferred = $q.defer();
$http.get('/testcase/' + $routeParams.testcase)
.success(function(data, status, headers, config)
deferred.resolve(data);
)
.error(function(data, status, headers, config)
deferred.reject("Error fetching XML file: " + status + ' ' + JSON.stringify(headers));
);
return deferred.promise;
;
]);
app.controller('testcaseCapCtrl', ['$scope', '$routeParams', '$timeout', 'getTestcaseFactory', function($scope, $routeParams, $timeout, getTestcaseFactory)
var fetchTestcaseDetails = function()
getTestcaseFactory.list()
.then(
function(data)
$scope.xml.file = data;
var x2js = new X2JS();
var jsonObj = x2js.xml_str2json($scope.xml.file);
$scope.xml.json = JSON.stringify(jsonObj, null, 2);
$scope.model = jsonObj;
console.log($scope.model);//PRINTS THE RIGHT DATA
,
function(data)
alert(data);
);
fetchTestcaseDetails();
$timeout(function()
console.log($scope.model); //Prints the Data now
, 2000);
]);
【讨论】:
这不是一个好的解决方案,尽管它可能大部分时间都有效。请在下面查看我的答案。【参考方案3】:到目前为止发布的解决方案根本上是错误的,因为它们依赖于任意超时,并且没有任何东西可以保证到那时异步答案可用。
正如我在上面的评论中所建议的,这里还有 2 个数据/事件驱动的解决方案。
-
你要么只在回调函数中打印 (你已经在你的例子中这样做了)
或者,既然您无论如何都在使用 angular,您可以设置一个手表 (它在后台使用不太好的脏检查解决方案,但至少它从您的代码中抽象出来)
如果您想在数据可用后运行一个名为 processData
的函数,您已经在示例中执行的解决方案 1,请参阅此行:
console.log($scope.model);//PRINTS THE RIGHT DATA
在这里你可以调用任何其他函数来触发进程的继续,只要调用任何函数:
console.log($scope.model);//PRINTS THE RIGHT DATA
processData();
使用 Angular 的 $watch 机制(2.):
$scope.$watch(
function()return $scope.model;,
function(newValue, oldValue)
if(newValue != null)
console.log($scope.model);
processData();
)
这将在异步回调后可用时打印数据,然后程序将继续处理。
【讨论】:
这很酷。我的第一种方法只是使用 $watch 方法。但后来我不知道究竟应该提到什么作为 watch 方法的第一个参数,所以我最终放弃了这种方法,而是采用了超时方法。无论如何,@doldt,感谢您的建议和帮助。我会立即实施。以上是关于获取从 angularJS 中的异步 $http 服务获得的对象,以便在 $scope 中全局访问的主要内容,如果未能解决你的问题,请参考以下文章
如何从 angularjs 中的 JSONP 错误回调中获取数据?