我正在创建一个工厂,从一个页面中获取用户ID,调用REST API,并在下面的视图中返回结果。我最初的尝试很大程度上是根据这个答案进行的,但不出所料,我一直处于这样一种情况:没有及时响应,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
),并且我找不到使用promise强制get()
等待set()
完成的方法。
我更愿意在最终的解决方案中继续使用Restangular,但这是一件花费了太多时间的小事,所以任何修复都有效。
我是Angular的新手,所以我相信有一些非常明显的东西,但现在我只是迷失了方向。谢谢
您的竞争条件是.then
方法中的函数在调用set函数后异步执行。如果get函数在$q
服务实现承诺之前执行,那么get函数将返回一个空数组。
解决方案是从promise中保存promise和链。
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
}
});
在您的控制器中,从承诺链接。
GetMessages.get.then( function (docs) {
$scope.messages = docs;
}) .catch ( function (error) {
//log error
};
有关链接承诺的更多信息,请参阅AngularJS$q服务API参考——链接承诺。
重新分配时,您正在破坏对原始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
cherlietfl是对的。
问题是,由于在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
});
尝试将函数分配给作用域。然后在模型中调用该函数。像这样:
// controller
$scope.getMessages = GetMessages.get;
视图:
<div ng-repeat="message in getMessages()"></div>
这样,当请求调用完成,摘要循环再次通过观察者时,将调用get函数,您将获得消息。