2

我使用Angular Service從API中獲取細節,我只想返回匹配項。意思是,在我鍵入一些文本後,我將點擊一個按鈕,這將調用控制器中的一個函數,該函數將調用服務以獲取詳細信息。Angular Service不過濾數據

現在我的問題是,它返回整個列表而不是過濾列表,我已經將過濾結果存儲到一個數組中,我想返回該數組(foundItems)。

這是我的代碼

(function() { 
angular.module('NarrowItDownApp',[]) 
.constant('url',"https://davids-restaurant.herokuapp.com/menu_items.json") 
.controller('NarrowItDownController',['$scope','MenuSearchService',function($scope,MenuSearchService) { 
    var items=this; 
    items.searchitem=""; 
    items.getitems=function() { 
     MenuSearchService.getMatchedMenuItems(items.searchitem).then(function(response) { 
      this.found=response.data; 
      console.log(this.found); 
     }) 
     .catch(function(response) { 
      this.found=response.data; 
      console.log(this.found); 
     }); 
    }; 
}]) 
.service('MenuSearchService',['$http','url',function($http,url) { 
    var service=this; 
    service.getMatchedMenuItems=function(searchitem) 
    { 
     var foundItems=[]; 
     var key; 
     return $http.get(url).success(function(data) { 
      for(var i=0;i<data.menu_items.length;i++) 
      { 
       var temp=data.menu_items[i]; 
       //Old method 
       /*for(key in temp) 
       { 
        if(temp.hasOwnProperty(key)) 
        { 
         console.log(temp[key]) 
        } 
       }*/ 
       Object.keys(temp).forEach(function(items) 
       { 
        if(searchitem==temp[items]) 
        { 
         foundItems.push(temp); 
        } 
       }); 
      }; 
      console.log(foundItems); 
      return foundItems; 
     }) 
     .error(function(data) { 
      console.log('error'); 
      return data; 
     }); 
     return foundItems; 
    }; 
}]); 
})(); 
+2

本身並不是答案,但如果是我,我會下載整個json並將其公開在控制器中。從此,可以使用html中的簡單過濾器完成搜索。認爲這會留下更好的用戶體驗,因爲它只需要一個異步http請求。 – cYrixmorten

+0

請參閱[爲什麼不推薦使用角度$ http成功/錯誤方法?從v1.6中刪除?](http://stackoverflow.com/a/35331339/5535245)。 '.success'和'.error'方法**忽略**返回值。 – georgeawg

回答

3

現在我的問題是,它返回整個列表中未過濾列表,我已存儲的過濾結果到一個數組我想返回數組(foundItems)。

該服務返回整個列表的原因是.success.error方法忽略返回值。改爲使用.then.catch

service.getMatchedMenuItems=function(searchitem) 
{ 
    var foundItems=[]; 
    var key; 
    //return $http.get(url).success(function(data) { 
    //USE .then method 
    return $http.get(url).then(function(response) { 
     var data = response.data; 
     for(var i=0;i<data.menu_items.length;i++) 
     { 
      var temp=data.menu_items[i]; 
      Object.keys(temp).forEach(function(items) 
      { 
       if(searchitem==temp[items]) 
       { 
        foundItems.push(temp); 
       } 
      }); 
     }; 
     console.log(foundItems); 
     return foundItems; 
    }) 
    //.error(function(data) { 
    //USE .catch method 
    .catch(function(errorResponse) { 
     console.log(errorResponse.status); 
     //return data; 
     //THROW to chain rejection 
     throw errorResponse; 
    }); 
    //return foundItems; 
}; 

此外,在拒收處理程序中使用throw statement也很重要。否則被拒絕的承諾將被轉換爲成功承諾。請參閱Angular execution order with $q

+0

它工作完美兄弟我現在有一個查詢,因爲我已經檢查了服務中的錯誤我需要再次檢查它在控制器我的意思是詢問有關(承諾)。有必要嗎? – Kannan

+1

不,您不需要'.catch'控制器中的錯誤,因爲它們是'.caught'並登錄到服務中。但是,重新拋出錯誤非常重要,這樣它就不會**轉換**成功。 – georgeawg

-1

更新

發生的事情,因爲你有一個異步回調函數,但仍然有其外部回報。所以當你的服務被調用時,異步函數開始運行,但由於過早的回調,沒有機會實現其回調。

此外,您沒有從您的服務中返回承諾,但是您的方法調用有一個.then()。

您的服務方法更改爲以下:

.service('MenuSearchService',['$http','url',function($http,url) { 
    var service=this; 
    service.getMatchedMenuItems=function(searchitem) 
    { 
     return new Promise(function(resolve, reject){ 
      var foundItems=[]; 
      var key; 

      $http.get(url).success(function(data) { 
       for(var i=0;i<data.menu_items.length;i++) 
       { 
        var temp=data.menu_items[i]; 
        //Old method 
        /*for(key in temp) 
        { 
         if(temp.hasOwnProperty(key)) 
         { 
          console.log(temp[key]) 
         } 
        }*/ 
        Object.keys(temp).forEach(function(items) 
        { 
         if(searchitem==temp[items]) 
         { 
          foundItems.push(temp); 
         } 
        }); 
       }; 
       console.log(foundItems); 
       resolve(foundItems); 
      }) 
      .error(function(data) { 
       console.log('error'); 
       reject(data); 
      }); 
     })   
    }; 
}]); 

希望的作品!

+0

他需要返回一個承諾,在控制器中調用.then()。他怎麼能在foundItems上調用回調函數? –

+0

@Rohan Kanjani不會工作 – Kannan

+0

@ kannucodert14檢查我的編輯! –

-1

您可以使用承諾爲Promise

(function() { 
angular.module('NarrowItDownApp', []) 
.constant('url', "https://davids-restaurant.herokuapp.com/menu_items.json") 
.controller('NarrowItDownController', ['$scope', 'MenuSearchService', function($scope, MenuSearchService) { 
    var items = this; 
    items.searchitem = ""; 
    items.getitems = function() { 
     MenuSearchService.getMatchedMenuItems(items.searchitem).then(function(data) { 
       for (var i = 0; i < data.menu_items.length; i++) { 
        var temp = data.menu_items[i]; 
        //Old method 
        /*for(key in temp) 
        { 
         if(temp.hasOwnProperty(key)) 
         { 
          console.log(temp[key]) 
         } 
        }*/ 
        Object.keys(temp).forEach(function(items) { 
         if (searchitem == temp[items]) { 
          foundItems.push(temp); 
         } 
        }); 
       }; 

       this.found = foundItems); 
       console.log(this.found); 
      }) 
      .catch(function(response) { 
       this.found = response.data; 
       console.log(this.found); 
      }); 
    }; 
}]) 
.service('MenuSearchService', ['$http', 'url', function($http, url) { 
    var service = this; 
    service.getMatchedMenuItems = function(searchitem) { 
     var foundItems = []; 
     var key; 
     return $http.get(url);    
    }; 
}]); 
})(); 
+1

請參閱[爲什麼不推薦使用角度$ http成功/錯誤方法?從v1.6中刪除?](http://stackoverflow.com/a/35331339/5535245)。 – georgeawg

+0

感謝@georgeawg的更新。更新了相同的代碼。 –

+1

因爲'$ http'服務已經返回一個承諾,所以沒有必要用'$ q.defer'來製造承諾。看看[這是一個「延遲Antipattern」?](http://stackoverflow.com/questions/30750207/is-this-a-deferred-antipattern)。另外,由於處理不當,承諾將會出現錯誤。 – georgeawg