In my service-factory I lookup up a large dataset - I want to persist it and check for its existence to avoid calling it again

本秂侑毒 提交于 2019-12-24 06:38:15

问题


My service (factory) makes an API call and assigns response data to a variable:

    .factory('MedicationMatchingNamesFactory', 
                ['$http', '$q', 'MedicationDisplayNamesFactory', 
                    function MedicationMatchingNamesFactory($http, $q, MedicationDisplayNamesFactory){

        return {
            getMatchingNames: function(inputValue){

                var matches = [];

                // I thought this may be set as null so I'm able to 
                // differentiate it from the below array form (when exists)
                var allNames = null;

                    MedicationDisplayNamesFactory.getDisplayNames().then(
                            function(response){

                                // this is the large dataset - now as array
                                var allNames = response.data.displayTermsList.term;

                                angular.forEach(allNames, function(value, key){

                                    if(value.indexOf( inputValue ) !== -1){
                                        matches.push(value);
                                    }

                                });
                            }
                        );


                return matches;
            }
        };
        return MedicationMatchingNamesFactory;
    }])

I'm using Angular-UI's "ui-select" directive to search within this large dataset based on entered string.

In my controller:

        $scope.$on('inputStarted', function(event, value){
            if(value.length > 3){
                $scope.meds.displayNames = MedicationMatchingNamesFactory.getMatchingNames(value);
                console.log($scope.meds.displayNames);
            }
        });

Now, to avoid querying the API (actually call another service containing the call to API) every time the number of input characters is greater than 3, I think it would be great if I'm able to check whether allNames is null (empty, do call API) or it's an array (skip the call, just use that).

I tried moving the angular.forEach part outside the call and promise but then, obviously, nothing happens because it's not resolved yet on the first run.

Is there a way to have this allNames dataset checked before I do the API call?


回答1:


You can move the declaration of allNames outside the return statement of your service, and then check if it's null before querying the API. That way allNames serves as a cache for the results of the inner API call.

Also, note that it would be better if you return a promise from getMatchingNames, otherwise your service always returns a blank array right away, which then gets filled later, after the inner API call is completed. If you do return a promise, you would need to change the way you are setting displayNames in your inputStarted event handler:

    MedicationMatchingNamesFactory.getMatchingNames.then(function(matches) {
      $scope.meds.displayNames = matches;
    });

and your service could look like this:

    .factory('MedicationMatchingNamesFactory',
      ['$http', '$q', 'MedicationDisplayNamesFactory', 
        function MedicationMatchingNamesFactory($http, $q, MedicationDisplayNamesFactory) {

          var allNames = null;

          function getMatches(inputValue, list){
            var matches = [];
            angular.forEach(list, function(value, key){
              if(value.indexOf(inputValue) !== -1){
                matches.push(value);
              }
            });
            return matches;
          }

          return {
            getMatchingNames: function(inputValue){
              var deferred = $q.defer();

              if (allNames !== null) {
                deferred.resolve(getMatches(inputValue, allNames));
              } else {
                MedicationDisplayNamesFactory.getDisplayNames().then(
                  function(response){
                    // this is the large dataset - now as array
                    allNames = response.data.displayTermsList.term;
                    deferred.resolve(getMatches(inputValue, allNames));
                  },
                  function(reason){
                    deferred.reject(reason);
                  }
                );
              }
              return deferred.promise;
            }
          };
        }])



回答2:


Actually the solution to this problem is very simple: I just went with the sessionStorage which seems to fit perfectly my needs in this case as I need the big dataset persisted just for this session and it doesn't matter if it's lost on the next one. The goal is to prevent fetching it more than once, that is, more than necessary, as the values inside are not likely to be changed during that session.



来源:https://stackoverflow.com/questions/26169188/in-my-service-factory-i-lookup-up-a-large-dataset-i-want-to-persist-it-and-che

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!