2017-09-15 97 views
2

我有一個物品數組,我將從localStorage獲得。在AngularJS中有條件地創建一個承諾

    var items = JSON.parse($window.localStorage.selectedResources)['server']; 

        var arr = []; 

        var idsArray = []; 

        angular.forEach(items, function (item) { 
         idsArray.push(item.id); 
        }); 

然後我火API調用...

    //Make the API call 
        ds.getBillInfo(idsArray) 
         .then(function(response){ 
          var serversList = []; 
          for (var key in response) { 
           // iterate over response 

的問題是,如果項目數組是空的,所以做了idsArray。 然後錯誤說Cannot read property 'then' of undefined

我想要做的是even if the idsArray is empty , I want lines to execute inside the then block thinking as there is no promise

我該怎麼做?

編輯

如果我做$q.all([ds.getBillInfo(idsArray)])那麼就沒有錯誤。

getBillInfo()樣子:

 this.getBillInfo = function(idsArray){ 
      if(!idsArray.length) return; 
      var segmentUrl = ''; 
      for(var i =0;i<idsArray.length;i++){ 
       if(i != (idsArray.length-1)) 
        segmentUrl += 'ids='+idsArray[i]+'&'; 
       else 
        segmentUrl += 'ids='+idsArray[i]; 
      } 
      return HttpWrapper.send('/api/bill?bill=t&'+segmentUrl, {"operation": 'GET'}); 
     }; 
+1

您需要修改'getBillInfo'總是返回一個承諾 – SLaks

+0

東西是不正確這裏...喜歡@SLaks說。 – Pytth

+0

...即使返回類似'Promise.reject('empty')'的東西也會工作,並且最終會在catch或Promise.resolve()中解析 – adeneo

回答

2

getBillInfo包裝你的邏輯和新的承諾和空陣列上解決這個問題。

是這樣的:

self.getBillInfo = function(array){ 

    var deferred = $q.defer(); 

    if(array.length == 0){ 
    deferred.resolve([]); // return empty list 
    } 
    else{ 
    var segmentUrl = ''; 
    for(var i =0;i<idsArray.length;i++){ 
     if(i != (idsArray.length-1)) 
      segmentUrl += 'ids='+idsArray[i]+'&'; 
     else 
      segmentUrl += 'ids='+idsArray[i]; 
     } 
     HttpWrapper.send('/api/bill?bill=t&'+segmentUrl, {"operation": 'GET'}) 
     .then(function (response) { 
       deferred.resolve(response.data); 
     } 
     , function (error) { 
       deferred.reject(error); 
     }); 

    } 

    return deferred.promise; 
} 

[編輯]

問候@JC Ford點,由於HttpWrapper返回答應我們可以寫上面的邏輯與不同的方式爲:

self.getBillInfo = function(array){ 

    if(array.length == 0){ 
    return $q.resolve([]); // return empty list; 
    } 
    else{ 
    var segmentUrl = ''; 
    for(var i =0;i<idsArray.length;i++){ 
     if(i != (idsArray.length-1)) 
      segmentUrl += 'ids='+idsArray[i]+'&'; 
     else 
      segmentUrl += 'ids='+idsArray[i]; 
     } 
     return HttpWrapper.send('/api/bill?bill=t&'+segmentUrl, {"operation": 'GET'});   
    } 
} 
+0

如果'HttpWrapper.send'已經返回一個promise,這是多餘的。它會起作用,但是使用'$ q.defer()'實際上是爲了在你還沒有的時候創造一個承諾。這過於複雜,因此不是最佳實踐。 –

+0

@JCFord同意,但它看起來很清楚,無論如何我會用你的方式更新答案;) –

+0

使用'$ q.resolve([])'而不是延遲。 – SLaks

1

注入$ q服務,以便在getBillInfo()中可訪問。然後,您可以將值包含在$q.resolve()中以作出返回該值的承諾。 (這個值甚至可能是另一個承諾。)因此,如果你的getBillInfo()函數有時需要提前返回而沒有值,那麼只需返回一個空的$q.resolve(),以確保你總是返回一個承諾。

this.getBillInfo = function(idsArray){ 

    //This returns undefined and causes your error. 
    if(!idsArray.length) return; 

    //This returns a promise that resolves immediately and executes your .then() handler. 
    if(!idsArray.length) return $q.resolve(); 

    //This returns a promise that rejects immediately and executes your .catch() handler 
    if(!idsArray.length) return $q.reject(); 

    var segmentUrl = ''; 
    for(var i =0;i<idsArray.length;i++){ 
     if(i != (idsArray.length-1)) 
      segmentUrl += 'ids='+idsArray[i]+'&'; 
     else 
      segmentUrl += 'ids='+idsArray[i]; 
    } 
    return HttpWrapper.send('/api/bill?bill=t&'+segmentUrl, {"operation": 'GET'}); 
}; 
+0

注意你有'if(!idsArray.length)return'的地方。而是返回$ q.resolve()。 –