如何在没有 运行 竞争条件的情况下使用 getter 和 setter 方法创建 Angular 工厂
How can I create an Angular factory with a getter and setter method without running into a race condition
我正在创建一个工厂以从一个页面获取 userId,调用 REST API,然后 return 以下视图中的结果。我最初的尝试主要来自 this answer,但不出所料,我一直陷入无法及时响应且 get()
方法 return 是一个空数组的情况。
这是工厂本身
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()
我遇到的问题是,在工厂 returns 空集之后,没有识别出工厂的进一步更改(即使在时间过去后它确实从 API) 和 $scope.messages
保持为空。
我试图将 API 调用移动到 get 方法(这没有用,因为 get 方法通常不能及时获得 userId
),但我做不到找到一种使用承诺强制 get()
等待 set()
完成的方法。
我更愿意在最终解决方案中继续使用 Restangular,但这是一件花费太多时间的小事,因此任何修复都有效。
我是 Angular 的新手,所以我确信有一些非常明显的东西,但现在我只是迷路了。谢谢。
您在重新分配时破坏了对原始 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 是对的。
问题是您破坏了对 messages 数组的引用,因为您在 get 函数中为 messages 分配了一个新数组。但是 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 函数,您将收到消息。
您遇到的竞争条件是 .then
方法内的函数在调用 set 函数后 异步执行。如果 get 函数在 之前 执行 $q
服务履行承诺,则 get 函数 returns 一个空数组。
解决方案是从 promise 中保存 promise 和 chain。
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 Service API Reference -- chaining promises。
我正在创建一个工厂以从一个页面获取 userId,调用 REST API,然后 return 以下视图中的结果。我最初的尝试主要来自 this answer,但不出所料,我一直陷入无法及时响应且 get()
方法 return 是一个空数组的情况。
这是工厂本身
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()
我遇到的问题是,在工厂 returns 空集之后,没有识别出工厂的进一步更改(即使在时间过去后它确实从 API) 和 $scope.messages
保持为空。
我试图将 API 调用移动到 get 方法(这没有用,因为 get 方法通常不能及时获得 userId
),但我做不到找到一种使用承诺强制 get()
等待 set()
完成的方法。
我更愿意在最终解决方案中继续使用 Restangular,但这是一件花费太多时间的小事,因此任何修复都有效。
我是 Angular 的新手,所以我确信有一些非常明显的东西,但现在我只是迷路了。谢谢。
您在重新分配时破坏了对原始 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 是对的。
问题是您破坏了对 messages 数组的引用,因为您在 get 函数中为 messages 分配了一个新数组。但是 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 函数,您将收到消息。
您遇到的竞争条件是 .then
方法内的函数在调用 set 函数后 异步执行。如果 get 函数在 之前 执行 $q
服务履行承诺,则 get 函数 returns 一个空数组。
解决方案是从 promise 中保存 promise 和 chain。
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 Service API Reference -- chaining promises。