2013-12-17 193 views
0

我在角度服務中承諾存在問題。我有一個方法getArea服務,它應該返回服務區的名稱。該服務從API獲取服務區域。當getArea獲得服務區時,它會找到所請求區域的名稱,並將其返回。但是,我的代碼不起作用 - 我陷入了無限循環。我想我誤解了如何使用承諾?

SupplierService:

var servicePromise; 
var getServices = function(){ 
    if(!servicePromise){ 
     servicePromise = $http.get('/api/services') 
      .then(function(res){ 
       return res.data.data; 
      }); 
    } 
    return servicePromise; 
}; 


var myService = { 

    getServices : getServices, 

    getArea : function(questionnaireId){ 
     getServices().then(function(services){ 
      // ... 
      return "hello world"; 
     }); 
    } 
}; 

return myService; 

控制器:

$scope.supplierService = SupplierService; 

查看:

<div> 
    <b>Area:</b> {{ supplierService.getArea(r.questionnaireId) }} 
</div 

我想到的看法顯示「區域:你好世界」,但進入無限循環。


更新1:我已經加入getServices作爲服務大衆的功能,並且可以從控制器這樣的訪問:

SupplierService.getServices().then(function(d){ 
    $scope.services = d; 
}); 

所以我想這個問題是在getArea方法?


更新2:我被這個答案https://stackoverflow.com/a/12513509/685352啓發。我想緩存結果。


更新3:這裏是一個plunker。如果您嘗試從視圖中訪問supplierService.getArea(100) - 瀏覽器將不會響應。

回答

2

您的服務應該看起來更像是這樣的:

var getServices = function(){ 
    var deferred = $q.deferred(); 
    $http.get('/api/services') 
      .then(function(res){ 
       deferred.resolve(res.data) 
      }); 
    return deferred.promise; 
}; 

注意當您創建必須調用延遲一個延遲必須退回deferred.promise(實際的承諾),然後當你異步調用返回(分別觸發成功或錯誤功能)

小的添加我有一個plunkr顯示了從服務中獲取數據到控制器的幾種方法,因爲這是開發人員遇到的常見問題into Angular

http://plnkr.co/edit/ABQsAxz1bNi34ehmPRsF?p=info

這是因爲我試圖保持儘可能簡單,不是絕對的最佳實踐,但基本呈現「共享」你的數據記住其中的一些方法依賴於angular.copy這意味着三種不同的方法存儲數據的服務的屬性必須是對象或數組(由於不能共享引用,基本類型將不起作用)。

這裏包括內聯函數重寫:

var myService = { 
    var dataLoaded = false; 
    var data = {}; //or = []; 
    getServices : function(){ 
     var deferred = $q.defer(); 
     if(!dataLoaded){ 
      $http.get('/api/services').then(function(res){ 
       angular.copy(res.data, myService.data); 
       deferred.resolve(myService.data); 
      }, function(err){ 
       deferred.reject("Something bad happened in the request"); 
      }); 
     } 
     else 
     { 
      deferred.resolve(myService.data); 
     } 
     return deferred.promise; 
    } 
}; 

return myService; 

要解釋,我創建一個使用它,你需要注入的服務功能$ Q服務的新承諾。這使我可以用我已經擁有的數據解決承諾,或者調用服務並解析數據,但是在使用這兩種情況下,假設您只是得到一個承諾,並因此處理異步操作。如果你有多個數據集要加載,你可以使用一個對象來存儲標誌而不是一個布爾值。

+1

+1 $ q服務,Angular的精益承諾服務將被注入。你當然可以返回__ $ http.get('/ api/services')__,因爲它已經是一個承諾。 – cbayram

+0

好點的cbayram,我傾向於這樣做,並使用一個對象來檢查,如果我已經加載數據(存儲每個服務調用的屬性,我將在服務中知道數據是否加載) ,我想我已經習慣了「明確地」這樣做,但就像你說的使用從get返回的HttpPromise我想象的是一個很好的解決方案。 – shaunhusain

+0

「getArea」方法不是問題嗎?實際上,我也返回getServices方法,並在異步調用返回時在控制器中獲取服務。 – swenedo

0

我想如果你返回$ http回調?

//$http.get('/someUrl').success(successCallback); 


var getServices = function(){ 
    return $http.get('/api/services'); 

}; 

getServices.success(function(services){ 
// ... 
      return "hello world"; 
     }); 
    }