我创建工厂以从一个页面获取userId,调用REST API,并在以下视图中返回结果。我最初的尝试主要来自this answer但是 - 毫不奇怪 - 我一直处于不及时响应并且get()
方法返回空数组的情况下。
这是工厂本身
app.factory('GetMessages', function() {
var messages = []
function set(userId) {
Restangular.all('/api/messages/').getList({'_id': userId}).then(function(docs){
messages = docs
})
}
function get() {
return messages;
}
return {
set: set,
get: get
}
});
对于它的价值,我可以毫不费力地将userId带入工厂,因为它只是传递了这样的功能
视图:
<a ng-click='passToFactory(message.user.id)' href='/home/inbox/reply'>Reply</a>
控制器:
$scope.passToFactory = function(id) {
GetMessages.set(id);
};
以下视图的控制器就是
$scope.messages = GetMessages.get()
我遇到的问题是,在工厂返回空集后,不会识别出工厂的进一步更改(即使经过一段时间后它确实从API获得了正确的响应)并且$scope.messages
仍然是空的。
我试图将API调用移到get方法(由于get方法通常无法及时获得userId
,因此无法运行)我无法做到找到一种方法来使用承诺强制get()
等待set()
完成。
我更喜欢在最终的解决方案中继续使用Restangular,但这是一件小事,因为任何修复工作都需要花费太多时间。
我对Angular相当陌生,所以我确定有一些非常明显的东西,但现在我只是输了。感谢。
答案 0 :(得分:1)
你遇到的竞争条件是.then
方法中的函数在调用set函数后异步执行。如果get函数在<{strong>之前执行<{1}}服务执行承诺时执行,则get函数返回一个空数组。
解决方案是从承诺中保存承诺和链。
$q
在您的控制器中,来自承诺的链。
app.factory('GetMessages', function() {
var promise;
function set(userId) {
promise = Restangular.all('/api/messages/').getList({'_id': userId});
}
function get() {
return promise;
}
return {
set: set,
get: get
}
});
有关链接承诺的详情,请参阅AngularJS $q Service API Reference -- chaining promises。
答案 1 :(得分:0)
重新分配时,您正在断开对原始messages
数组的引用。
尝试:
Restangular.all('/api/messages/').getList({'_id': userId}).then(function(docs){
messages.concat(docs) ; // keep same array reference
});
简单的例子来解释它为什么不起作用
var arr = [];
var x = arr;
arr = [1,2,3]; // is now a different array reference
console.log(x); // is still empty array. x !== arr now
答案 2 :(得分:0)
cherlietfl是对的。
问题是你破坏了对messages数组的引用,因为你为get函数中的消息分配了一个新数组。但是concat
也是这样做的。
试试这个:
Restangular.all('/api/messages/').getList({'_id': userId}).then(function(docs){
messages.splice(0, messages.length); // clear the array
messages.push.apply(messages, docs); //add the new content
});
答案 3 :(得分:0)
尝试将功能分配给范围。然后在模型中调用该函数。像这样:
// controller
$scope.getMessages = GetMessages.get;
查看:
<div ng-repeat="message in getMessages()"></div>
这样,当请求调用完成并且摘要周期再次通过观察者时,将调用get函数,您将收到消息。