我正在尝试从URL获取一些数据,将其存储在变量中并将其返回给我的控制器。但问题是,在变量已经返回到控制器(调用该函数)之后,处理来自URL的数据。我在 Service.js 中调用服务网址 我是这样做的:
var demoService = angular.module('demoService', []).service('myService', function($http, $q) {
var gaugeData = {
maxValue: 5000,
animationSpeed: 100,
val: 5000
};
console.log(gaugeData);
var deferred = $q.defer();
$http.get('http://myurl').then(function(data) {
console.log(data.data.Tweets[3].FAVOURITE_COUNT);
var gaugeData = {
maxValue: 5000,
animationSpeed: 100,
val: data.data.Tweets[3].FAVOURITE_COUNT
};
deferred.resolve(gaugeData);
console.log(gaugeData);
});
this.get = function() {
deferred.promise.then(function(data) {
console.log(data);
gaugeData.val = data.val;
});
return gaugeData;
};
function sleep(milliseconds) {
var start = new Date().getTime();
for (var i = 0; i < 1e7; i++) {
if ((new Date().getTime() - start) > milliseconds) {
break;
}
}
}
this.list = function() {
return gaugeData;
};
});
控制器期望数据的形式与gaugeData
对象相同,但由于gaugeData
在返回值后填充了服务数据,因此控制器不显示任何对象( undefined )。控制台如下所示:
Object {maxValue: 5000, animationSpeed: 100, val: 5000}
controllers.js:202 $…t.l.$…w.a.$…e.$$ChildScope {$$childTail: null, $$childHead: null, $$nextSibling: null, $$watchers: null, $$listeners: Object…} (console.log); from controller
app.js:15 TypeError: Cannot read property 'maxValue' of undefined (since an empty value is passed)
1566
services.js:137 Object {maxValue: 5000, animationSpeed: 100, val: 1566}
services.js:144 Object {maxValue: 5000, animationSpeed: 100, val: 1566}
显然,控件首先进入服务,然后在处理URL时,控件跳转到控件并获取一个空值,在此之后,URL被处理并且gaugeData
被值填充来自服务URL。
我试着这样做,没有承诺,推迟了。我只是使用了$http.get(url).success(function(){code});
如何将我的URL数据传递给变量并在正确的时间将其正确传递给控制器?
此处还有我的控制器代码片段,我正在调用服务函数:
console.log($scope);
return $scope.gaugeHome ={
gaugeData:
myService.get(), .....
答案 0 :(得分:1)
不要将现有的承诺包含在新的延期中;这是一种反模式。 $http
已经返回了一个承诺,您可以通过return
来自then
处理程序的新承诺或值来修改承诺。
您无法返回同步值,该值是异步操作的结果。这是一个基本矛盾。如果你需要返回最终会被设置为值的东西,那就是承诺的全部要点。您的服务应返回一个承诺,然后您的控制器将致电then
。
您的sleep
功能令人担忧。看起来你正在使用繁忙的循环以便...做什么?挂CPU一段时间?为什么?为什么不只是$timeout
?
这是您的服务版本,A)获取资源一次,B)将其存储在承诺中,C)让消费者(控制者)要求承诺。然后,控制器必须调用then
来决定如何处理结果。
如果您希望您的服务能够更新资源,您可以将promise生成包装在一个再次运行fetch并返回新promise的函数中。然而,目前还不完全清楚你的最终目标是什么,所以我没有表现出这种方法。
var demoService = angular.module('demoService', []).service('myService', function($http, $q) {
var gaugePromise = $http.get('http://myurl').then(function(response) {
var updatedGuageData = {
maxValue: 5000,
animationSpeed: 100,
val: response.data.Tweets[3].FAVOURITE_COUNT
};
return updatedGuageData;
});
this.get = function() {
return gaugePromise;
};
});
现在,您可以让服务将值缓存为同步对象(沿着您尝试的行),并且每当异步获取它时,更新缓存作为副作用(就像你在做的那样)。但是,每当你进行异步更新时,你才知道它成功(或失败)的唯一一次是使用回调或承诺处理程序,这使得缓存的同步值毫无意义 - 为什么不只是使用结果async直接?更简单。