2

I have an items array that I would be getting from localStorage.

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

                    var arr = [];

                    var idsArray = [];

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

Then I fire an API call ...

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

The problem is if the items array is empty, so does the idsArray. Then the error says Cannot read property 'then' of undefined.

What I want to do is even if the idsArray is empty , I want lines to execute inside the then block thinking as there is no promise.

How can I do that ?

EDIT

If I do $q.all([ds.getBillInfo(idsArray)]) then there is no error.

The getBillInfo() looks like:

     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'});
        };
6
  • 1
    You need to fix getBillInfo to always return a promise Commented Sep 15, 2017 at 17:37
  • Something isn't right here... Like @SLaks said. Commented Sep 15, 2017 at 17:38
  • ...even returning something like Promise.reject('empty') would work, and you'd end up in the catch, or Promise.resolve() to resolve Commented Sep 15, 2017 at 17:39
  • @Pytth Please see the update, my method returns a promise. Commented Sep 15, 2017 at 17:48
  • 1
    @StrugglingCoder: No, it doesn't; otherwise, you wouldn't have a problem. Read the very first line. Commented Sep 15, 2017 at 18:21

2 Answers 2

2

In getBillInfo wrap your logic with new Promise and on empty array resolve it.

Something like:

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;
}

[EDIT]

Regards to @JC Ford point, since HttpWrapper returns Promise we can write above logic with different way as:

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'});        
  } 
}
Sign up to request clarification or add additional context in comments.

2 Comments

If HttpWrapper.send already returns a promise, this is redundant. It will work, but the use of $q.defer() is really for creating a promise when you don't already have one. This is overly complicated and thus not best practice.
@JCFord agree, but it looks clear, anyways I'll update answer with your way ;)
1

inject the $q service so that it is accessible in getBillInfo(). You can then wrap a value in $q.resolve() to make a promise that returns that value. (That value could even be another promise.) So if your getBillInfo() function sometimes needs to return early without a value, just return an empty $q.resolve() instead to ensure you're always returning a promise.

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'});
};

1 Comment

Note where you have if(!idsArray.length) return. Return $q.resolve() there instead.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.