0

I need to run a function "searchBoats(boatType)" in AngularJS 1.0.7 with a parameter. This parameter is the result of another function parseBoatType which is running a service that calls an API with a $resource. How can I run searchBoats when the boatType is returned in the resource with promises?

This is what I tried:

    var parseURL = function() {                                                         
            var deferred = $q.defer();
            var promise = deferred.promise;
            promise.then(function success (result) {                    
                console.log(result);
                searchBoats(result);
            });

            deferred.resolve(
                parseBoatType()
            );                                                                                                                                                                                                                          
        };      
        parseURL();

var parseBoatType = function() {

        //  Do some stuff        
        // Calculate boatType calling a service that uses resource to call 
        // an API
        // I can convert this callback into a promise but still facing same 
        // issue
        BoatType.getBoatTypeByName({name: boatTypeParsed}, function success(result) {
                return result;
            });

        // The service method is called and the code is still running until 
        // the end of the function without waiting for the service result.
        // Then the promise.then code in the parseURL is executed and 
        // searchBoats is run with boatType undefined.                                  
    };

 // The service with the $resource call to the API
.factory('BoatType', 

  function($resource, SERVER_URL){          
    var boatTypes =
     $resource('http://' + SERVER_URL +'/:action', {action:'boat_types'}, {       
        query: {method:'GET', isArray: true},           
        getBoatTypeByName: {method:'GET', params:{action: 'getBoatTypeByName'}, isArray: false}
     });        
     return boatTypes;           
  }
  )
Rober
  • 5,868
  • 17
  • 58
  • 110
  • 1
    I would link back to your previous question: [How to run functions with dependencies](https://stackoverflow.com/q/46306740/691711) so that others can get additional context of your problem. I'm glad you were able to figure out your issue. – zero298 Sep 21 '17 at 15:02

1 Answers1

1

You can return the resource $promise from the BoatType resource in the parseBoatTime function and use the promise to resolve the parseUrl deferred.

First return a promise from the parseBoatTime function:

return BoatType.getBoatTypeByName({
    name: boatTypeParsed
  }, function success(result) {
    return result;
  }).$promise;

Then resolve the parseUrl deferred with the promise from the BoatType resource:

parseBoatType().then(deferred.resolve);

Bellow is the full code taken from your question with the correction I mentioned.

var parseURL = function() {
  var deferred = $q.defer();
  var promise = deferred.promise;
  promise.then(function success(result) {
    console.log(result);
    searchBoats(result);
  });

  parseBoatType().then(deferred.resolve);
};
parseURL();

var parseBoatType = function() {

  //  Do some stuff        
  // Calculate boatType calling a service that uses resource to call 
  // an API
  // I can convert this callback into a promise but still facing same 
  // issue

  // Code for ngResource@^1.2.0
  /*return BoatType.getBoatTypeByName({
    name: boatTypeParsed
  }, function success(result) {
    return result;
  }).$promise;*/

  // Code for ngResource lower than 1.2.0
  var deferred = $q.defer(), promise = deferred.promise;

  BoatType.getBoatTypeByName({
    name: boatTypeParsed
  }, deferred.resolve, deferred.reject);

  return promise;

  // The service method is called and the code is still running until 
  // the end of the function without waiting for the service result.
  // Then the promise.then code in the parseURL is executed and 
  // searchBoats is run with boatType undefined.                                  
};

// The service with the $resource call to the API
app.factory('BoatType',
  function($resource, SERVER_URL) {
    var boatTypes =
      $resource('http://' + SERVER_URL + '/:action', {
        action: 'boat_types'
      }, {
        query: {
          method: 'GET',
          isArray: true
        },
        getBoatTypeByName: {
          method: 'GET',
          params: {
            action: 'getBoatTypeByName'
          },
          isArray: false
        }
      });
    return boatTypes;
  }
)
lenilsondc
  • 9,590
  • 2
  • 25
  • 40
  • I think I have copied/pasted your code, but I´m getting this error: TypeError: Cannot read property 'then' of undefined in this line parseBoatType().then(deferred.resolve); Just in case, it´s important I´m using Angular 1.0.7. – Rober Sep 21 '17 at 06:15
  • @Rober, it's indeed, this `$promise` property was introduced on [ngResource@1.2.0](https://code.angularjs.org/1.2.0/docs/api/ngResource) in this case you'll have to use promises like in the first function. I'll update my answer can you hint that version stuff in your question? – lenilsondc Sep 21 '17 at 11:21
  • Updated! ;) You are my hero! – Rober Sep 21 '17 at 14:50
  • Your answer is working! But, just to put the icing on the cake, how would it be if instead of just one parseBoatType function there would be two different functions that can run in parallel (a second parseDestination), but both need to be run before execute searchBoats? I think they can be nested, but is it possible to do it in parallel maybe with $q.all? – Rober Sep 21 '17 at 15:04
  • I will create a new post extending this one with this topic here: https://stackoverflow.com/questions/46348382/angularjs-1-0-7-nesting-parallel-promises-with-resources – Rober Sep 21 '17 at 15:56