我试图获得factory
JSON
响应,将其保存在变量中,以便准备从2个不同的controllers
调用。
下面我将使用以下代码粘贴代码:
storyFactory.js
var story = angular.module('story.services', []);
story.factory('storyAudio', [ '$http', function ($http) {
var json = {};
function getJSON(story_id, callback) {
$http({
url: 'https://api.domain.co/get/' + story_id,
method: "GET"
}).success(function (data) {
json = data;
callback(data);
});
};
return {
getSubaudios: function(story_id, callback) {
getJSON(story_id, function(result) {
callback(result);
});
},
getTopbar: function(callback) {
callback(json);
}
};
}]);
StoryCtrl.js
var storyCtrl = angular.module('story', ['story.services']);
storyCtrl.controller('storyCtrl', [ 'CONFIG', '$stateParams', 'storyAudio', function(CONFIG, $stateParams, storyAudio) {
var data = this;
data.story = {};
storyAudio.getSubvideos($stateParams.story_id, function(response) {
data.story = response;
});
}]);
TopbarCtrl.js
var topbarCtrl = angular.module('topbar', ['story.services']);
topbarCtrl.controller('topbarCtrl', [ 'CONFIG', '$stateParams', 'storyAudio', function(CONFIG, $stateParams, storyAudio) {
var data2 = this;
data2.story = {};
storyAudio.getTopbar(function(response) {
data2.story = response;
});
}]);
问题出在我的TopbarCtrl响应中,当我在HTML中调用它时,我收到一个空的data2.story。
原因是因为它没有$http
响应的回调,所以它打印var json
的实际状态,即空对象。
如果变量有内容,我怎么能加载第二个控制器?
感谢您的建议。
答案 0 :(得分:3)
我认为在这种情况下你能做的最好的事情是通过getSubaudios
加载数据,并提供对其他控制器使用的数据的引用。像这样......
story.factory('storyAudio', function($http) {
var factory = {
story: {}
};
factory.getSubaudios = function(story_id) {
return $http.get('https://api.domain.co/get/' + story_id).then(function(response) {
return angular.extend(factory.story, response.data);
});
};
return factory;
})
使用angular.extend()
而不是直接为工厂的story
属性赋值可以维护在加载数据之前可能建立的任何引用。
然后您可以通过
加载数据storyCtrl.controller('storyCtrl', function(storyAudio) {
var data = this;
storyAudio.getSubaudios($stateParams.story_id).then(function(story) {
data.story = story;
});
})
并通过控制器中的引用直接引用story
数据
topbarCtrl.controller('topbarCtrl', function(storyAudio) {
this.story = storyAudio.story;
})
答案 1 :(得分:1)
我认为我理解正确,但如果没有,请告诉我。
我看到了两个问题。首先是你的StoryCtrl.js文件中有一个拼写错误。您正在调用“storyAudio.getSubvideos”,但该函数在您的工厂中称为“getSubaudios”。
即使修正了错字,问题仍然可能在技术上发生。这一切都取决于承诺从第一次通话返回的速度。不幸的是,promises是异步的,因此无法保证在第二个控制器尝试获取之前设置“json”变量。
为了解决这个问题,您需要确保在尝试访问服务上的“json”变量之前完成第一个调用。可能有几种不同的方法可以做到这一点,但我想到的一种方法是实际返回并将承诺存储在服务中,如此......
var dataPromise;
function getSubaudios(story_id){
if(!dataPromise){
dataPromise = $http({
url: 'https://api.domain.co/get/' + story_id,
method: "GET"
});
}
return dataPromise;
}
return {
getSubaudios: getSubAudios
};
然后在您的控制器中,您可以调用该服务并使用.then在数据返回时从数据中获取数据...
storyAudio.getSubaudios($stateParams.story_id).then(function(response){
data.story = response; //or data2.story = response;
});
这是一个plunkr示例。我已经使用$ q库来模拟从$ http请求返回的promise,但它应该说明这个想法。
答案 2 :(得分:1)
与菲尔的答案相似。 (角度扩展或角度复制使两个控制器中的引用保持相同。如果您不想在两个控制器中放置观察者以跟踪值是否发生变化。)这里有几种方法: Share data between AngularJS controllers。
您还可以将要返回的对象直接绑定到update-function。这样参考文献保持不变。
storyServices.factory('storyAudio', ['$http', function($http) {
return {
data: { json: '' },
getSubaudios: function(story_id) {
$http.get('http://jsonplaceholder.typicode.com/posts/' + story_id)
.then(function(response) {
this.data.json = response.data.body;
}.bind(this));
}
};
}]);
var storyCtrl = angular.module('story').controller('storyCtrl', ['$scope', 'storyAudio', function($scope, storyAudio) {
$scope.data = storyAudio.data;
storyAudio.getSubaudios(2);
}]);
var topbarCtrl = angular.module('story').controller('topbarCtrl', ['$scope', 'storyAudio', function($scope, storyAudio) {
$scope.data2 = storyAudio.data;
}]);
在这里插入:http://plnkr.co/edit/auTd6bmPBRCVwI3IwKQJ?p=preview 我添加了一些范围来说明会发生什么。
我认为直接命名你的非控制者" storyCtrl"是不诚实的。然后为它分配一个自己的控制器:
var storyCtrl = angular.module(...); // Nooo, this is not a controller.
storyCtrl.controller(...); // This is a controller! Aaaah!
.success()
是旧的做事方式。立即更改为.then(successCallback)
!我敢说它是承诺的标准惯例。
https://docs.angularjs.org/api/ng/service/$http#deprecation-notice