簡體   English   中英

如何在不遇到競爭條件的情況下使用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,然后在以下視圖上返回結果。 我最初的嘗試主要是從這個答案中獲取的,但是-毫不奇怪-我一直陷入這種情況,即及時沒有響應並且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的新手,所以我敢肯定有些事情是完全顯而易見的,但現在我迷路了。 謝謝。

您所具有的競爭條件是.then方法中的函數在調用set函數之后異步執行。 如果get函數 $q服務履行諾言之前執行,則get函數返回一個空數組。

解決方案是保存承諾承諾中的 鏈條

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函數中的消息分配了新的數組,因此您破壞了對message數組的引用。 但是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函數,您將獲得消息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM